Swift - 函数,闭包,解除闭包循环引用

摘要:闭包类似于 OC 的bock,但是比OC的block应用更广;在OC 中block是匿名的函数;在swift中 函数是特殊的闭包。
应用的场景:
1,异步执行完成回调
2,控制器间的回调
3,自定义视图回调

函数

  • 函数的定义

函数 的定义 : 函数名(形参列表) -> 返回值

    // 有参有返回值
    func sum(x: Int,y: Int) -> Int {
        return x + y
    }
    // 无参无返回值
    func demo()  {
        print("安抚按时")
    }
    // 有参无返回值
    func demo1(x: Int) -> () {
        print("afdssd")
    }
    // 无参有返回值
    func demo2() -> Int {
        return ("afasf")
    }
  • 外部参数

外部参数 (就是咋形参前加一个名字,不会影响函数内部细节)
作用 : 让外部调用更加直观

    func sum1(num1 x: Int, num2 y: Int) -> Int {
        return x + y;
    }
// 在swift 中 “—”可以忽略一切 不感兴趣的内容
    func sum2(_ x: Int, _ y: Int) -> Int {
        return x + y
    }
  • 函数默认值

通过给参数设置默认值,在调用的时候可以任意组合,如果不指定则使用默认值OC 中需要定义很多方法,以及方法实现,最终调用包含所有参数的那个函数swift中可以设置默认值,解决这种问题

    func sum3(x: Int = 1, y: Int = 2) -> Int {
        return x + y
    }

闭包

  • 闭包的定义

() -> () 没有参数没有返回值的 闭包
没有参数,没有返回值,可以省略 ,连 in 都神略了

        let b1 = {
            print("adfa")
        }

闭包中参数返回值实现都是写在{}里面 {形参列表 -> 返回值 实现}
in 分割声明 与 实现

        let b2 = {(x: Int) -> () in
            print(x)
        }
        let b3 = {(x: Int) -> Int in
            return x + 150
        }
  • 闭包的回调,尾随闭包

"尾随闭包" 如果函数最后一个参数是闭包,函数参数可以提前结束 最后一个参数直接用{}包装闭包的代码

    func loadData(comlpant: @escaping (_ resoult: [String]) -> ()) -> () {
        // 将任务添加到队列,指定执行人的函数(闭包) 以同步/异步 执行
        
        DispatchQueue.global().async {
            print("耗时操作\(Thread.current)")
            
            // 消耗时间
            Thread.sleep(forTimeInterval: 1)
            
            let json = ["affas","afdasf","fd"]
            
            // 主队列回调
            DispatchQueue.main.async {
                print("主线程更新UI\(Thread.current)")
                
                // 闭包回调
                comlpant(json)
            }
        }
    }
        // 调用
        loadData { (resoult) in
            print(resoult)
        }

解除闭包循环引用

MRC: MRC 中没有weak,弱引用都是assign ,不会增加引用计数,但是指针指向对象释放,指针地址不会改变,会出现野指针异常
ARC : 在ARC中弱引用都用weak,不会增加引用计数,但是指针指向对象释放,指针地址会自动置为nil,更加安全__unsafe_unretained 与assign一样

实现循环引用
  1. 定义尾随闭包
    // 第一步: 定义尾随闭包
    func loadData (completion:@escaping ()->()) -> () {
        
        // 第四步 self 持有闭包,造成互相持有,循环引用
        complateCallBack = completion
        
        // 异步执行
        DispatchQueue.global().async {
            print("这是耗时操作")
            DispatchQueue.main.async {
                // 回调闭包
                completion()
            }
        }
    }
  1. 闭包持有self. (注意:闭包中出现self 要特别小心,循环引用,循环引用的条件就是互相持有)
 // 第二步: 闭包持有self,单方向的引用
        loadData {
            print(self.view);
        }
  1. 定义闭包属性
    //第三步 定义闭包属性
    var complateCallBack:(()->())?
  1. 形成循环引用
// 类似OC dealloc
    deinit {
        print("类似dealloc")
    }
解除循环引用

(1) 使用OC的方式 __Weak
注意: weak 可能被在运行时修改,指针指向的对象一旦被释放,指针会自动置为nil,指针地址改变了,所以 weak只能 用var来修饰

        weak var WeakSelf = self
        loadData {
            print(WeakSelf?.view as Any)
        }

(2) swift推荐方法
[weak self] 表示{}中所有的self都是弱引用,需要注意解包

    loadData {[weak self] in
            print(self?.view as Any)
        }

(3)另一个方法,了解
[unowned self] 表示{}中所有self 都是assign,不会强引用,但是对象释放,指针地址不会变化,继续调用就会出现野指针问题

        loadData {[unowned self] in
            print(self.view)
        }

最后来一波无耻的广告:淘劵吧

你可能感兴趣的:(Swift - 函数,闭包,解除闭包循环引用)