之前看了网上很多大牛写了对@weakify @strongify的解析,大部分讲解的非常详细,写这篇文章是为了加深自己对ReactiveObjC中@weakify @strongify的理解。
在OC代码中,为了防止在block中防止循环引用导致的内存泄漏,通常使用__weak来修饰的weakSelf来指向self,,而为了防止因为控制器销毁而导致weakSelf为nil,所以在block内部需要加上加上__strong来强引用weakSelf。例如:
__weak typeof(self) weakSelf = self;
[[self.btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
// 为了保证 block 再传出去 vc 之后被销毁, block 仍能正常运行
// strongSelf 是 weakSelf 进行了强引用引用
__strong typeof (weakSelf) strongSelf = weakSelf;
strongSelf.textField1.text = @"PJRAC";
}];
在ReactiveObjC
@weakify(self);
[[self.btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
// 为了保证 block 再传出去 vc 之后被销毁, block 仍能正常运行
// strongSelf 是 weakSelf 进行了强引用引用
@strongify(self);
self.textField1.text = @"PJRAC";
}];
通过看预处理结果可以看出,上面两者预编译结果是一样的
预处理结果.png通过预处理结果我们可以看出ARC下weakify前面的@就是@autoreleasepool {},那么一步步往里看,点击weakify,可以看到
#define weakify(...) \ rac_keywordify \ metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)
rac_keywordify点击进去就是
#define rac_keywordify autoreleasepool {}
metamacro_foreach_cxt点击进去
#define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \ metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)
那么替换下来就是
autoreleasepool {} \ metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(rac_weakify_, , __weak, self)
下面来研究一下metamacro_argcount(__VA_ARGS__)这个宏
#define metamacro_argcount(...) \ metamacro_at(20, __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
metamacro_argcount(__VA_ARGS__)中__VA_ARGS__放入的是可变参数,参数是几个就表示几,例如:
metamacro_argcount(@"pj1",@"pj2")==2
metamacro_argcount(self)==1。
接下来看一看metamacro_concat
#define metamacro_concat(A, B) \ metamacro_concat_(A, B)
我嚓,这里是宏又重新定义了一遍,再点击进去(后面会在简书上写文章说明为什么要这样)
#define metamacro_concat_(A, B) A ## B
这里用宏链接符将AB连接在一起,好的,我们将上面的再“翻译”一遍
autoreleasepool {} \ metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(rac_weakify_, , __weak, self)
等同于
autoreleasepool {} metamacro_foreach_cxt1 (rac_weakify_, , __weak, self)
走到这里就要开始研究metamacro_foreach_cxt1是什么东西???
我们载工程里搜索 metamacro_foreach_cxt1
metamacro_foreach_cxt1 .png这里有metamacro_foreach_cxt1 ~metamacro_foreach_cxt20(建议最多传20个参数)
autoreleasepool {} metamacro_foreach_cxt1 (rac_weakify_, , __weak, self)
#define metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0)
可以转换成
autoreleasepool {} rac_weakify_(0,__weak, self)
这里的rac_weakify
#define rac_weakify_(INDEX, CONTEXT, VAR) \ CONTEXT __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR);
最终替换成
autoreleasepool {} __weak __typeof__(self) self_weak_ = self
网友评论