码迷,mamicode.com
首页 > 编程语言 > 详细

【Swift4.2】循环引用的例子讲解

时间:2018-12-20 14:34:53      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:elf   private   getter   vat   遇到   引用计数   类型   error   init   

最近又想回顾下swift,现在版本已经到4.2了。。。想当时15年,我写swift2.1的时候,我遇到了很多让我感到尴尬的场景。。

https://www.cnblogs.com/rayshen/p/5038937.html

这边博客现在看起来还非常搞笑,但是当时确实是这样。好在我之前说的这些问题,在后来的swift版本中,都已经给纠正过来了(感觉swift语言组也好水)……

 

这次要回顾的是循环引用,这个是老生常谈的问题。在block和delegate中,如果两个对象A和B,A强引用B,B又强引用A时,A的引用计数就会变成2,这样就会造成A无法自动释放。

 

看一段示例代码:

class Example{

    private var name = "123";

    /// 正确用法1
    lazy private var rightClosure1:()->() = { [unowned self] in
        print("name is \(self.name)")
    }

    /// 正确用法2
    lazy private var rightClosure2:()->() = { [weak self] in
        print("name is \(self?.name ?? "")")
    }

    /// 函数用法不存在该问题
    private func commonFunction(){
        print("name is \(self.name)")
    }

    /// 错误用法
    lazy private var errorCycleClosure1:()->() = {
        print("name is \(self.name)")
    }
    
    /// 错误用法(函数赋值给errorCycleClosure2,errorCycleClosure2变成一个闭包对象被引用,函数是这个闭包的实现)
    lazy private var errorCycleClosure2 = commonFunction;

    func startRight1() {
        rightClosure1()
    }

    func startRight2() {
        rightClosure2()
    }

    func startRight3() {
        commonFunction()
    }
    
    func startError1() {
        errorCycleClosure1()
    }
    
    //需要特殊警惕的情况,一旦函数被赋值给一个被引用的对象后,也会出现循环引用的情况
    func startError2() {
        errorCycleClosure2()
    }

    deinit{
        print("Example deinit")
    }

}

var example:Example? = Example()
//调用正确例子1,example=nil后能正常销毁
//example?.startRight1();
//调用正确例子2,example=nil后能正常销毁
//example?.startRight2();
//调用正确例子3,example=nil后能正常销毁(函数不存在循环引用问题)
//example?.startRight3();
//调用错误例子1,example=nil后没有调用deinit,说明有残留成员变量
//example?.startError1();
//调用错误例子2,example=nil后没有调用deinit,说明有残留成员变量
example?.startError2();
example=nil;

 

 

这里面有几个swift的知识点:

1.lazy的用法:所谓的lazy就是懒加载,在没有被getter访问时,他不进行初始化。在这里,一个闭包初始化中访问到self,因为self在此时还没生成所以需要添加lazy修饰,使他们在被访问到时才初始化。

2.[unowned self]和[weak self]和区别: [unowned self]调用closure的时候如果对象已经被释放的话,会出现crash。

3.为什么函数直接调用没影响:因为函数在内存中只分配函数地址,不是一个对象。而闭包是一个对象,是个引用类型,会被实例对象所引用,如果闭包再引用实例对象本身,就会出现循环引用。

【Swift4.2】循环引用的例子讲解

标签:elf   private   getter   vat   遇到   引用计数   类型   error   init   

原文地址:https://www.cnblogs.com/rayshen/p/10148499.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!