33.以弱引用避免保留环

《编写高质量iOS与OS X代码的52个有效方法》--第五章 第33条
(ps:此乃读书笔记,加深记忆,仅供大家参考)


第33条 以弱引用避免保留环

对象图里经常会出现一种情况,就是几个对象都以某种方式互相吸引,从而形成“环”(cycle)。由于Objective-C内存管理模型使用引用计数架构,所以这种情况通常会泄漏内存,因为最后没有别的东西会引用环中的对象。这样的话,环里的对象就无法为外界所访问了,但对象之间尚有引用,这些引用使得它们都能继续存活下去,而不会为系统所回收。

@class EOCClassA, EOCClassB;

@interface EOCClassA : NSObject
@property (nonatomic, strong) EOCClassB *other;

@end

@interface EOCClassB : NSObject
@property (nonatomic, strong) EOCClassA *other;

@end

保留环会导致内存泄漏。如果只剩一个引用还指向保留环中的实例,而现在又把这个引用移除,那么整个保留环就泄露了。

避免保留环的最佳方式就是弱引用。这种引用经常用来表示“非拥有关系”(nonowning relationship)。将属性声明为unsafe_unretained即可。

@class EOCClassA, EOCClassB;

@interface EOCClassA : NSObject
@property (nonatomic, strong) EOCClassB *other;

@end

@interface EOCClassB : NSObject
@property (nonatomic, unsafe_unretained) EOCClassA *other;

@end

属性特质(attribute)中的unsafe_unretained一词表明,属性值可能不安全,而且不归此实例所拥有。如果系统已经把属性所指的那个对象回收了,那么在其上调用方法可能会使应用程序崩溃。由于本对象并不保留属性对象,因此其有可能为系统所回收。

Objective-C中还有一项与ARC相伴的运行期特性,可以令开发者安全使用弱引用:这就是weak属性特质,它与unsafe_unretained的作用完全相同。然而,只要系统把属性回收,属性值就会自动设为nil。(ps:而对nil发送消息并不会使程序崩溃)

当指向EOCClassA实例的引用移除后,unsafe_unretained属性仍然指向那个已经回收的实例,而weak属性则指向nil。

一般来说,如果不拥有某对象,那就不要保留它。这条规则对collection例外,collection虽然并不直接拥有其内容,但是它要代表自己所属的那个对象来保留这些元素。有时,对象中的引用会指向另外一个并不归自己所拥有的对象,比如Delegate模式就是这样。

要点

  • 将某些引用设为weak,可避免出现“保留环”。
  • weak引用可以自动清空,也可以不自动清空。自动清空(autonilling)是随着ARC而引入的新特性,由运行期系统来实现。在具备自动清空功能的弱引用上,可以随意读取其数据,因为这种引用不会指向已经回收过得对象。

你可能感兴趣的:(33.以弱引用避免保留环)