剖析@weakify 和 @strongify

前言

使用RAC的时候我们常会看到这两个宏@weakify(self)@strongify(self),用来防止使用block时出现引用闭环。 今天看YYKit的时候,看到里面也写了类似的宏,还是来谈谈这两个宏是怎么实现的吧。

正文

## 宏定义代码 由于YYKit中的weakify、strongify相对比较简单,所以只剖析RAC(2.5)中的weakify、strongify。

一点一点剥开。

weakify

rac_keywordify

这段宏定义中的代码开头都少了个@,使得weakify、strongify前面必须加上@,当然也只有这作用。 然后这里为什么要判断DEBUG呢?我也不知道,我觉得这里没必要这样判断。

metamacro_foreach_cxt(rac_weakify_,, weak, __VA_ARGS)

先看看最外面的宏定义metamacro_concat:

这里有点弄不懂再套一层宏定义的意图,##的作用是连接两个运算符。

1.然后这个宏的实现变成了这样

MACRO、SEP、CONTEXT这三个参数先不管 __VA_ARGS__是可变参数,获取在...中传入的N个参数。

2.metamacro_argcount(__VA_ARGS__)

metamacro_argcount这个宏的作用是获得参数的个数。 为什么能获得参数的个数呢? 我们看看是怎么实现的

拼接metamacro_at##N(传入的第一个值,这里是20)(VA_ARGS) 也就是:

metamacro_at20的实现这样的:

截取前20个数,剩下的传入metamacro_head

metamacro_head的作用返回第一个参数。 打个比方:@weakify(self),

截取前20个参数,那么就应该是metamacro_head_(1),那么返回的就是1。 多个参数同理。

3.回到metamacro_foreach_cxt

metamacro_argcount既然返回的是参数个数那么就可以变成这样:

N是参数个数 还是以@weakify(self)打比方:

metamacro_foreach_cxt1的实现是这样的

4.到了这里我们就要回到之前传入的三个参数了

代入这些参数就应该是

先不管rac_weakify_如何实现,我们再来看看N=20的时候是怎么实现的。

这里就有点类似递归了,先rac_weakify_(0,__weak,_19), 然后把前19个数传入metamacro_foreach_cxt19metamacro_foreach_cxt19rac_weakify_(0,__weak,_18),然后把前18个数传入metamacro_foreach_cxt18…直到metamacro_foreach_cxt1。 而且它是存在保护机制的,要是N=0

就不做任何操作。 然后我们再来看rac_weakify_实现了什么。

rac_weakify_的实现

INDEX只是第几个的标记,在这里没实际作用。 拿@weakify(self)打比方: rac_weakify_(0,__weak,self) 就会变成这样:

self_weak_是弱化后的self。 @weakify(self)就这么实现了。

再看看strongify

rac_keywordify

和之前同理,只是为了前面必须加@。

_Pragma语句

可能有人会不太了解_Pragma是什么,其实大家都用过它的前身:

换过来就是:

这里的clang语句的作用:忽略当一个局部变量或类型声明遮盖另一个变量的警告 clang的对照表可以看fuckingclangwarnings

metamacro_foreach

拿@strongify(self)打比方,metamacro_foreach(rac_strongify_,, self)

即:

metamacro_foreach_cxt

即:

即:

metamacro_foreach_iter

即:

rac_strongify_

即:

这个时候你在项目中敲入:

你会发现你有一个错误,Redefinition of 'self',重新定义了自己。 一定要注意__strong __typeof__(self) self = self_weak_只能在block里面用。

RAC写法:

@wexxx、@strxxx是不会联想的,只会联想wexxx、strxxx,所以为了顺手的话还是把这两句加入到自己的代码段。使用Code Snippet在Xcode中添加代码段 多个参数情况其实和@weakify(xxx)的多个参数情况是一样的,这就就不重复了。

后记

对宏的运用来说,可以说,RAC的作者是我目前见过最强的。 本以为剖析起来应该花不了多少功夫,可是着实绞尽脑汁了。 我尽量捋清思路,但也就这样了..大家将就着看吧.. 要是有哪里不对或者不好,欢迎指出!

最后分享一下心得:

“多看源码,多去推敲”。

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

1 3 收藏 评论

关于作者:WzxJiang

本职iOS开发,却想成为一名全栈,在学习过程中分享自己的心得。 个人主页 · 我的文章 · 1 ·    

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部