使用weak strong dance 解决 block 循环引用
Posted 芒果味ly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用weak strong dance 解决 block 循环引用相关的知识,希望对你有一定的参考价值。
写在前面的话
使用 block 的时候很容易造成循环引用,使用 ARC 编译与否解决的办法也不一样,这里简单总结下,需要硬性的记住类型也是很烦的一件事,如果能自动推断出类型就好了,这里介绍一个保留的函数实现自动推断变量类型,最后总结出 weak strong dance 的宏。
循环引用的产生
首先看个引发循环引用的例子:
@interface Example ()
@property (nonatomic, strong) Maker *maker;
@end
@interface Maker ()
@property (nonatomic, copy) void(^cookieMaked)(int count);
@end
- (void)makeCookie
[self.maker makeCookie:^(int count)
[self makeCookieSucc:count];
];
Example 持有了 Maker ,Maker 持有了 cookieMaked , cookieMaked 保留了 example 对象!这样就构成了闭环,造成了内存泄露!下面就来解决这个问题,不过 ARC 与否还不一样,因此分开说吧。
非 ARC 编译
这里采取不让 cookieMaked 保留 example 对象的方式打破闭环:
- (void)makeCookie
__block Example *this = self;
[self.maker makeCookie:^(int count)
[this makeCookieSucc:count];
];
这里 __block 的作用相当于 __unsafe_unretained ,意思是不会保留被修饰的对象,就这样解决了循环引用问题!
使用 ARC 编译
以上写法在非 ARC 下有效,但是 ARC 下是不行的!!!可以在 WWDC 2011 section 322 里找到答案,简单总结下 ARC 编译的情况:
__block 等同于默认的 __storng; 因此 ARC 下不能再使用 __block 解决 block 保留问题!
而是使用 __weak 替代 __block ;
如果非要使用 __block 那么需要这样写 __block __unsafe_unretained
Example *this = self;
weak strong dance
所谓 weak strong dance 就是在 block 外部创建一个 weak 的对象,block 内部创建一个 strong 的对象,weak 目的很明显解决 block 循环引用的,strong 的意图是在 block 执行期间持有对象,保证对象的安全性:
__weak Example *this = self;
[self.maker makeCookie:^(int count)
__strong Example *self = this;
[self makeCookieSucc:count];
];
推断变量类型
发现每次解决 block 循环引用问题都要定义一个类型和 self 一样的新变量,确实很麻烦,即使写个宏也要传个类型进去,很麻烦的说!后来找到了一个 GNU c函数,能够推断出变量或者表达式的类型,他就是 typeof() ;LLVM 编译器下最好还是使用__typeof(),因为编译器版本不同时有可能不识别 typeof();有了这么爽的方法后,就可以写个完美的宏了:
#define __weakself __weak __typeof(self)__weakSelf = self;
#define __strongself __strong __typeof(__weakSelf) self = __weakSelf;
上面的 weak strong dance 将改写为:
__weakself;
[self.maker makeCookie:^(int count)
__strongself;
[self makeCookieSucc:count];
];
有时候不仅仅是 self ,也可能是别的对像,因此写个通用的宏很有必要:
#define weakify(_obj) __weak __typeof(_obj) _weak##_obj = _obj;
#define strongify(_obj) __strong __typeof(_weak##_obj) _obj = _weak##_obj;
既然有了通用宏了,那就把 weakself ,strongself 的宏改下吧:
#define __weakself weakify(self)
#define __strongself strongify(self)
哈哈,有了这些宏,就不怕 block 带来的循环引用问题了!
以上是关于使用weak strong dance 解决 block 循环引用的主要内容,如果未能解决你的问题,请参考以下文章