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

Posted rayshen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift4.2循环引用的例子讲解相关的知识,希望对你有一定的参考价值。

最近又想回顾下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循环引用的例子讲解的主要内容,如果未能解决你的问题,请参考以下文章

request.getParameter讲解

常用python日期日志获取内容循环的代码片段

Python之如何优雅的重试

通过实例详细讲解PHP垃圾回收机制

内存泄漏典型例子

2016.06.05 周日 实训课第二课 “中断”讲解