美文网首页swiftswiftiOS开发技术
解析Swift中闭包的循环引用

解析Swift中闭包的循环引用

作者: 邻家菇凉 | 来源:发表于2015-11-25 19:52 被阅读7174次

    1.什么时候会发生循环引用

    原理跟OC中的block类似, 当有个属性记录下了函数传递回来的闭包, 产生强引用, 就会发生闭包的循环引用

    2.怎么解决循环引用

    如何解决闭包的循环引用, 同样有三种方式:

    • 使用weak修饰变量, 打破强引用, 因为使用weak修饰的变量有一次变成nil的机会

    • 使用[weak self] 修饰闭包原理跟__weak类似, 这样在闭包中使用self, 就是弱引用

    • 使用[unowned self ] 修饰闭包, 跟__unsafe_unretained类似, 不安全

    3.如何判断是否发生强引用, 闭包中使用析构函数

    • 代码:
    //swift dealloc
    
    //析构函数
    
    deinit{
    
    print("销毁")
    
    }
    
    • storyboard:
    748058-d28cabf10ff73b50.png

    4.Swift中的代码

    import UIKit
    
    class ViewController: UIViewController {
        var finishedCallBack: ( (dataString: String) -> () )?
        override func viewDidLoad() {
            super.viewDidLoad()
    
    //解决方式三: [unowned self]  跟 _unsafe_unretained 类似  不推荐使用 
            loadData { [unowned self] (dataString) -> () in
                print("\(dataString) \(self.view)")
            }  
        }
        
        func method2() {
            //解决方式二:  在swift中 有特殊的写法 ,跟OC __weak 相似  [weak self]
            loadData { [weak self] (dataString) -> () in
                
                //以后在闭包中中 使用self 都是若引用的
                print("\(dataString) \(self?.view)")
            }
        }
       
        func method1() {
            // 解决方式一: weak
            weak var weakSelf = self
            loadData { (dataString) -> () in
                print("\(dataString) \(weakSelf?.view)")
            }
        }
    
    
        func loadData(finished: (dataString: String) -> ()) {
            
            // 记录闭包
            self.finishedCallBack = finished
            //加载数据
            dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
                
                print("执行耗时操作")
                
                dispatch_async(dispatch_get_main_queue(), { () -> Void in
                    //执行回调
                    self.working()
                })
            }
        }
    
        
        func working() {
            self.finishedCallBack?(dataString: "<html>")
        }
        
        //swift dealloc
        //析构函数
        deinit {
            print("销毁")
        }
    }
    

    相关文章

      网友评论

      • Aacmr:楼主,请问一下:用闭包调方法,没有传值,这样会不会造成循环引用? 只有在传值的时候(当有个属性记录下了函数传递回来的闭包, 产生强引用, 就会发生闭包的循环引用),会造成循环引用吗? 不太清楚这个概念。
      • 乱尘:swift 里面枚举 结构体 数组 字典 字符串都是值传递是吧,那为什么闭包持有变量还有循环引用的说法呢????有点不太明白
        乱尘:var myString = "excuse me"
        let arr = ["yi lian mengbi",myString]
        myString = "SUPER"
        print(arr,"\n",myString)
        输出的数组的值和oc里面是不同的
        乱尘:这不应该是引用传递的事情吗,非类的实例都是值传递吧?为什么呢,想不明白
      • 落影loyinglin:当闭包和捕获的实例总是互相引用时并且总是同时销毁时,将闭包内的捕获定义为无主引用。
        相反的,当捕获引用有时可能会是nil时,将闭包内的捕获定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为nil。这使我们可以在闭包内检查它们是否存在。
        XIAODAO:总结的真好,学习了:+1:
      • 落影loyinglin:解决方案1没有weak-strong dance
      • 落影loyinglin:解决方式三: [unowned self] 跟 _unsafe_unretained 类似 不推荐使用
        我在另外一个地方看到的是推荐使用unowned self

      本文标题:解析Swift中闭包的循环引用

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