打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
iOS中使用ARC的注意事项

ARC也有其弱点,最大的一个就是循环保留。此外,LLVM的静态分析器不能检测循环保留。

1. 循环保留

当两个对象对彼此都有所有权时就会发生循环保留。一个经典的现实场景就是子视图控制器拥有指向父视图控制器的强指针,如图5-2所示。


图5-2 当拥有一个引用,而引用的对象是其父对象时,循环保留就会发生

为了避免这种循环保留,可以使用__weak(或者__unsafe_unretained)所有权修饰符。一个弱引用可以确保指针的引用计数的值不会增加,如图5-3所示。


图5-3 使用指向父对象的弱引用可以避免循环保留

如果你学会了使用所有权而不是release/retain,就可以在大多数情况下避免出现循环保留,当然block除外。在一定程度上block和ARC是很难兼容的。

2. block和ARC

block是可以捕获上下文的特殊代码块。也就是说,任何在block外可以访问的变量都可以在block中访问。捕获上下文是新的设计模式,第22章会详细介绍。当block“捕获”了上下文,它就会为其作用域内的每个标量变量创建一个副本。其中,这个作用域内每个Objective-C对象都会被保留。有一种常见的错误:通过self拥有一个block,而你又在block中修改了实例变量,这时就会出错。

会引发循环保留的代码

1234
    self.myBlock = ^(NSString* returnedString) {    self.labelControl.text = returnedString;    };

这段代码展示了同时使用ARC与block的一个典型陷阱。self保留了block,而block又捕获(保留)了self。这样就会引发循环保留。非常微妙,也很危险。

为了避免这种情况,需要在block中捕获未保留的self引用。在没有ARC时,我们可以使用__block关键字和__unsafe_unretained来复制一个未保留的引用副本,并在block中使用这个引用。

使用__block避免循环保留(无ARC)

12345
    __block id safeSelf = self;    self.myBlock = ^(NSString* returnedString) {    safeSelf.labelControl.text = returnedString;    };

ARC会改变__block的语义,因此不应使用它。在ARC中,__block引用会被保留而不是被复制,这意味着在ARC环境中前面的代码仍然会引发循环保留。正确的办法是使用__weak(或者unsafe_unretained)引用,如下面的代码所示:

使用__weak避免循环保留(有ARC)

1234567
    __weak id safeSelf = self; //iOS 5+    //__unsafe_unretained id safeSelf = self; //iOS 4+    self.myBlock = ^(NSString* returnedString) {    safeSelf.labelControl.text = returnedString;    }
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
iOS: ARC和非ARC下使用Block属性的问题
iOS block里的self
iOS进阶 - iOS(Objective-C) 内存管理
IOS中的block和retain cycle
【面试】iOS 开发面试题(三)
iOS 使用Block
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服