ARC大大减少了开发人员在内存管理上的工作量,但它还是存在着一个巨大的问题,那就是循环引用。其原因是在默认情况下,引用赋值时会被编译器认为是强引用,也就是引用计数会自动加一。在这个背景下,如果一个实例A中的一个属性引用了实例B,而实例B中又有一个属性引用了实例A,那么在外界不加干预的情况下,就会发生循环引用,并且产生内存泄漏。示例如下:
动手写 8.4.2 CycleReference
控制台输出如下:
控制台输出如下:
A和B的实例被正确地释放了。为示例增加两行代码:
A和B的实例被正确地释放了。为示例增加两行代码:
控制台输出如下:
A和B没有得到真正的释放,它们游离在内存中一个不能触及的地方。那该如何解决循环引用的问题呢?使用weak关键字即可。示例如下:
控制台输出如下:
A和B没有得到真正的释放,它们游离在内存中一个不能触及的地方。那该如何解决循环引用的问题呢?使用weak关键字即可。示例如下:
控制台输出如下:
控制台输出如下:
现在A和B又被正确释放了,因为weak关键字告诉编译器,在给这个变量赋值的时候并不进行引用计数的操作。此外,weak变量所引用的实例被释放时,weak变量会自动被置为nil。需要我们注意的是,weak只能用于变量,不能用于常量,也就是“weak var”。因为weak变量可能会变为nil,所以必须是可空类型。(www.xing528.com)
除了类中会产生循环引用外,闭包中也会产生循环引用,示例如下:
动手写8.4.3 ClosureCycleReference
现在A和B又被正确释放了,因为weak关键字告诉编译器,在给这个变量赋值的时候并不进行引用计数的操作。此外,weak变量所引用的实例被释放时,weak变量会自动被置为nil。需要我们注意的是,weak只能用于变量,不能用于常量,也就是“weak var”。因为weak变量可能会变为nil,所以必须是可空类型。
除了类中会产生循环引用外,闭包中也会产生循环引用,示例如下:
动手写8.4.3 ClosureCycleReference
控制台输出如下:
控制台输出如下:
Example的实例没有被释放,原因是闭包会捕获上下文,这里closure中需要修改self.property,这就使得闭包引用了self,而self又引用了closure。如果要解决这个循环,需要使用闭包的捕获列表。捕获列表的语法是在闭包传入参数前用方括号“[]”包起来的列表,示例如下:
Example的实例没有被释放,原因是闭包会捕获上下文,这里closure中需要修改self.property,这就使得闭包引用了self,而self又引用了closure。如果要解决这个循环,需要使用闭包的捕获列表。捕获列表的语法是在闭包传入参数前用方括号“[]”包起来的列表,示例如下:
这是self的捕获,是一个弱引用。因为self是弱引用,所以调用时变成可空类型。最终控制台输出如下:
这是self的捕获,是一个弱引用。因为self是弱引用,所以调用时变成可空类型。最终控制台输出如下:
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。