美文网首页
Swift语法--12-3闭包的循环引用

Swift语法--12-3闭包的循环引用

作者: 20b347b28fc9 | 来源:发表于2016-03-12 01:37 被阅读468次

    Swift语法--12-3闭包的循环引用


    闭包循环引用产生条件
    • 如果在HttpTool中有对闭包进行强引用,则会形成循环引用

    我们先看一段普通的代码

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    
            loadData { () -> () in
                print("被回调了")
                
                //在闭包中引用成员属性,需要加self
                //swift中能不写self就不写self
                //一般情况下只有区分参数,和在闭包中使用self
                self.view.backgroundColor = UIColor.greenColor()
            }
        }
        
        func loadData(finished: ()->())
        {
            callback = finished
            // 1.加载数据
            print("加载数据")
            
            // 2.执行回调
            finished()
            
            
        }
    
    

    当我们想把里面的闭包作为一个属性储存起来

    class ViewController: UIViewController {
        //设置属性用来保存闭包
        //成员属性要么初始化,要么设为可选类型
        //在设置闭包属性是可选类型时一定更要用一个()括住闭包的所有的类型, 否则只是指定了闭包的返回值是可选的
        // 错误写法: var callback: ()->()?
        var callback: (()->())?
        
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        
            loadData { () -> () in
                print("被回调了")
                self.view.backgroundColor = UIColor.greenColor()
                //闭包中强引用了self
            }
        }
    
        
        func loadData(finished: ()->())
        {
            callback = finished
            //viewController中的成员属性强引用了闭包
            
            // 1.加载数据
            print("加载数据")
            
            // 2.执行回调
            finished()
        }
    
        // deinit 相当于OC中的dealloc方法
        // 只要一个对象释放就会调用deinit方法
        deinit
        {
            print("88")
        }
    }
    
    闭包循环引用产生原因
    闭包循环引用产生原因
    解决方案
    方案1:
    • 使用weak,对当前控制器使用弱引用
    • 但是因为self可能有值也可能没有值,因此weakSelf是一个可选类型,在真正使用时可以对其强制解包
    • (该处强制解包没有问题,因为控制器一定存在,否则无法调用所在函数)
    // 解决方案一:   
        
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
            weak var weakSelf = self  //可选类型
           loadData { () -> () in
                print("被回调了")
                //注意这里的改变
                //要对weakSelf进行解包
                weakSelf!.view.backgroundColor = UIColor.greenColor()           
            }
        }
    
    方案2:
    • 和方案1类型,只是书写方式更加简单
    • 可以写在闭包中,并且在闭包中用到的self都是弱引用
    // 解决方案二:   
        
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        
            loadData {[weak self] () -> () in
                print("被回调了")
                //注意这里的改变
                self!.view.backgroundColor = UIColor.greenColor()           
            }
        }
    
    方案3:
    • 使用关键字unowned
    • 从行为上来说 unowned 更像OC中的 unsafe_unretained
    • unowned 表示:即使它原来引用的对象被释放了,仍然会保持对被已经释放了的对象的一个 "无效的" 引用,它不能是 Optional 值,也不会被指向 nil
    // 解决方案三:   
        
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        
            loadData {[unowned self] () -> () in
                print("被回调了")
                //注意这里的改变
                self.view.backgroundColor = UIColor.greenColor()           
            }
        }
    
    总结
    • OC中如何解决: __weak typeof(self) weakSelf = self;
    • Swift中如何解决: weak var weakSelf = self

    对应关系:

    • __weak == weak //如果对象释放, 会自动设置为nil
    • __unsafe_unretained == unowned //如果对象释放, 不会自动设置为nil,因此不是可选类型,因为一定有值

    相关文章

      网友评论

          本文标题:Swift语法--12-3闭包的循环引用

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