美文网首页iOS精品程序员Swift
Swift - 函数,闭包,解除闭包循环引用

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

作者: 逾期的誓言 | 来源:发表于2017-09-05 15:32 被阅读203次

    摘要:闭包类似于 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 - 函数,闭包,解除闭包循环引用

      本文链接:https://www.haomeiwen.com/subject/lqwujxtx.html