RAC中的宏浅析

讲道理刚刚学RAC的时候点击宏进去的话其实是一脸懵逼的,然后自己看了下又看了几篇文章也有了一定的了解现在就简单的介绍下。

一样的从@weakify着手,我们点击进去会看到下面的代码,其中关于rac_keywordify是在我的同类的文章中讲过,这里就不介绍了,这里主要想记录下metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)

//1、
 #define weakify(...) \
    rac_keywordify \
    metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)

其中...的意思宏定义中的省略号就是指一串数目不限的参数列表和__VA_ARGS__连用的话其实就是代表把...所代表的内容替换到__VA_ARGS__这个的位置。

所以我们去要去看的就是下面这个

//2、
metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)

然后点击进去看,我们就会发现有下面这么个东西

//3、
#define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \
        metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)

我们这里就让@weakify里面的参数为self,来说明,这里把上面的metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)替换成下面的这个

//4、
metamacro_concat(metamacro_foreach_cxt,metamacro_argcount(__VA_ARGS__))(rac_weakify_,,_weak,self)

接着我们再去看下metamacro_concat,我们会发现下面的这个东西

//5、
#define metamacro_concat(A, B) \
        metamacro_concat_(A, B)

然后我们再点进去看,会发现其实这个宏就是做了一个拼接,不过这里用到了转换宏是需要注意的,这里其实就是将A和B拼在一起

//6、
#define metamacro_concat_(A, B) A ## B

接着我们再来看下metamacro_argcount(...)),这个有什么用?其实这个宏就是帮你计算出你括号里面有传进来了几个参数。就比如说metamacro_argcount(@"sss",@"qqq");这样的话得到的就是2,然后我们上面传入的是一个self,所以metamacro_argcount(self)是为1的,因为代码4当中的metamacro_argcount(__VA_ARGS__)中的__VA_ARGS__被替换成了self。于是我们把4的代码再进行替换就会得到下面的这个式子

//7、
metamacro_foreach_cxt ## 1 (rac_weakify_,,_weak,self)

其实就是变成了

//8、
metamacro_foreach_cxt1(rac_weakify_,  , __weak, self)

我们点击metamacro_foreach_cxt1进去看,会发现还有cxt2,3,4,5,6,7,8,等等一直到20

//9、
#define metamacro_foreach_cxt0(MACRO, SEP, CONTEXT)
#define metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0)

#define metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \
    metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) \
    SEP \
    MACRO(1, CONTEXT, _1)

#define metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \
    metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \
    SEP \
    MACRO(2, CONTEXT, _2)

#define metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
    metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \
    SEP \
    MACRO(3, CONTEXT, _3)

#define metamacro_foreach_cxt5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \
    metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
    SEP \
    MACRO(4, CONTEXT, _4)

我们需要关注的就是下面这一行

//10、
#define metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0)
也就是说其实就是替换成了

//11、
rac_weakify_(0,__weak,self)

所以最终我们还剩下最后一步,去看rac_weakify_这个宏,这里的INDEX只是第几个ctx的标记,没有什么作用

//12、
#define rac_weakify_(INDEX, CONTEXT, VAR) \
    CONTEXT __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR);

所以最终其实我们就是变成了

//13、
__weak __typeof__(self) self_weak_ = self
@weakify()括号里面传入的参数可以最多达到20个就是因为metamacro_foreach_cxt这个最多到20。我们往里面传入参数的话直接往括号里面写就好了。如果我们传入多个参数的话也会做多个参数的weak,其实实现起来就像递归一样举个例子,就比如说ctx3又去用了ctx2。

#define metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \
    metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \
    SEP \
    MACRO(2, CONTEXT, _2)
还有就是需要注意的是@weakify在外界使用,@strongify是在block内部使用的,如果两者在外界使用没在block里面使用就会报错,因为这就好比转换成了下面的这个代码,self重复定义了。
__weak __typeof__ (self) self_weak_ = self;  
__strong __typeof__(self) self = self_weak_;
接着对于@strongify其实道理是一样的只不过最终转换的是这样子的。

__strong __typeof__(self) self = self_weak_;

接着我们再去看下metamacro_argcount(...),我们会发现下面的这一行

#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_at,这里我们还是拿metamacro_argcount(self)举例子

#define metamacro_at(N, ...) \
        metamacro_concat(metamacro_at, N)(__VA_ARGS__)
也就是说metamacro_argcount(...)首先替换成了下面的这个

metamacro_at(20, self, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
之后又变成了下面这个样子

metamacro_concat(metamacro_at, 20)(self, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
然后metamacro_concat这个代表的是连接的意思,所以又变成了

metamacro_at20(self, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
然后我们再进入metamacro_at20这里面进行查看

#define metamacro_at20(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, ...) 
metamacro_head(__VA_ARGS__)
其实也就是替换成了

metamacro_head(1)
再点击metamacro_head进去查看会发现下面的这个代码

#define metamacro_head(...) \
        metamacro_head_(__VA_ARGS__, 0)
然后我们再点击metamacro_head_进去查看,发现如下所示

#define metamacro_head_(FIRST, ...) FIRST
所以最后其实就是变成了下面所示

metamacro_head_(1)
所以得出的是1,如果有两个三个参数其实都是类似的只不过是metamacro_head(2,1)括号里面的内容改变了。


























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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值