项目中的宏定义
<pre>
define kSelfWeak __weak typeof(self) weakSelf = self
define kSelfStrong __strong typeof(weakSelf) strongSelf = weakSelf
</pre>
正常我们在使用block时会写出如下的代码:
<pre>
- (void)function{
kSelfWeak; //创建一个指向当前对象的弱引用
[teseObject callFunc:^{
kSelfStrong; //block内部定义一个指向当前对象的强引用
[strongself callFunc_1:....];
[strongself callFunc_2:....];
....
}];
}
</pre>
现在我们来带着问题分析一下上面的这个代码:
-
可不可以直接使用self?
不可以。因为这样block会强持有self对象,造成循环引用,从而导致内存泄露。 -
可不可以直接使用weakself?
看情况。由于weakself不会持有对象,因此不会造成循环引用的问题,但是使用weakself却会造成block执行不一致问题,试想一下上面的代码,当调用“callFunc_1”的时候weakself是有效的,但是当调用“callFunc_2”的时候weakself可能已经是nil了,这样就造成了block内执行不一致从而导致意想不到的结果 -
循环引用是不是都是坏人?
答案是否定的。当block开始执行的时候,strongself会去取self对象的值,如果此时self已经为nil,那么整个block执行期间strongself都是nil,如果self有效那么strongself就是利用了循环引用的特性保证了在block执行的时候self对象不会被析构,保证block执行的一致性。其实我们在编写业务代码的时候(很多第三方开源类库)中会利用到循环引用的这一特性来保证block中引用的对象在block执行的时候依然有效,但是切忌使用这样黑魔法的时候要在block执行结束后打破循环引用。由于strongself是block内部定义的变量,在block执行结束会由系统回收从而打破循环引用
<pre>
总结:使用strongself可以消除循环引用带来的内存泄漏,也可以保证block执行过程中的一致性。所以正常的业务代码我们都会使用上面的标准方式编写,只有特殊的情况才会利用block的特性写一些黑魔法的代码。
</pre>
网友评论