使用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 带来的循环引用问题了!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值