Objective C 的 Block
是一个很实用的语法,特别是与GCD结合使用,能够很方便地实现并发、异步任务。可是,若是使用不当,Block 也会引发一些循环引用问题(retain cycle
)—— Block 会 retain ‘self’,而 ‘self‘ 又 retain 了 Block。由于在 ObjC 中,直接调用一个实例变量,会被编译器处理成 ‘self->theVar’,’self’ 是一个 strong 类型的变量,引用计数会加 1,因而,self retains queue, queue retains block,block retains self。并发
解决 retain circle
Apple 官方的建议是,传进 Block 以前,把 ‘self’ 转换成 weak automatic 的变量,这样在 Block 中就不会出现对 self 的强引用。若是在 Block 执行完成以前,self 被释放了,weakSelf 也会变为 nil。less
示例代码:异步
1
2 3 4 |
__weak __typeof__(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [weakSelf doSomething]; }); |
clang 的文档表示,在 doSomething 内,weakSelf 不会被释放。但,下面的状况除外:async
1
2 3 4 5 |
__weak __typeof__(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [weakSelf doSomething]; [weakSelf doOtherThing]; }); |
在 doSomething 中,weakSelf 不会变成 nil,不过在 doSomething 执行完成,调用第二个方法 doOtherThing 的时候,weakSelf 有可能被释放,因而,strongSelf 就派上用场了:ide
1
2 3 4 5 6 |
__weak __typeof__(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ __strong __typeof(self) strongSelf = weakSelf; [strongSelf doSomething]; [strongSelf doOtherThing]; }); |
__strong
确保在 Block 内,strongSelf 不会被释放。wordpress
总结
- 在 Block 内若是须要访问 self 的方法、变量,建议使用 weakSelf。
- 若是在 Block 内须要屡次 访问 self,则须要使用 strongSelf。
参考
- I finally figured out weakSelf and strongSelf
- Is the weakSelf/strongSelf dance really necessary when referencing self inside a non-retained completion called from a UIViewController?
原文做者: lslin
原文连接: http://blog.lessfun.com/blog/2014/11/22/when-should-use-weakself-and-strongself-in-objc-block/