RAC 宏学习
1.动态参数个数的计算
metamacro_argcount(...)
这个宏是用来计算参数个数的,其实就是根据
__VA_ARGS__
可变原则,以及参数占位原则来实现的
#define diy_argcount(...)
定义了上面这个宏,里面的...
就是__VA_ARGS__
,如果写成
diy_argcount(1,2,3)
那么__VA_ARGS__
就是1,2,3
,稍微变化一下
#define diy_argcount_1(parm1,...)
#define diy_argcount(...) diy_argcount_1(__VA_ARGS__)
此时上面的diy_argcount_1
的__VA_ARGS__
就变成2,3
, parm1
就变成了1,再来看看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)
#define metamacro_at(N, ...) \
metamacro_concat(metamacro_at, N)(__VA_ARGS__)
假设我们代码是metamacro_argcount(obj1,obj2,obj3)
那么根据上面的宏变换下,就是
metamacro_at20(obj1,obj2,obj3,20,19,....2,1)
而
#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_at20(obj1,obj2,obj3,20,19,....2,1)
中前面的20个参数逐个应对_1,_2,_3...._20
这样的变量,也及时相当于
_0 = obj1,
_1 = obj2,
_2 = obj3,
_3 = 20,
_4 = 19
.
.
.
_19 = 4
这样metamacro_head(__VA_ARGS__)
中的__VA_ARGS__
就是3,2,1
而metamacro_head
定义如下
#define metamacro_head_(FIRST, ...) FIRST
那么metamacro_head_ (3,2,1)
就是3
也就是有三个参数的输入
2.@weakify(obj1,obj2,obj3)实现
如果weakify
只可以接受一个参数,这样的宏都会写
#define weakify(_1) __weak __typeof__(_1) _1##_weak_ = (_1)
我们可以通过动态获取参数个数的方法,拿到obj1, obj2, obj3
,再对他们每个rac_weakify_
简化下RAC以后的宏定义
#define rac_weakify_(VAR) \
__weak __typeof__(VAR) VAR##_weak_ = (VAR);
定义
#define rac_weakify_20(N,SEP,...) rac_weakify_(N)\
SEP\
rac_weakify_19(__VA_ARGS__)
#define rac_weakify_19(N,SEP,...) rac_weakify_(N)\
SEP\
rac_weakify_18(__VA_ARGS__)
.
.
.
#define rac_weakify_1(N) rac_weakify_(N)
那么weakify
宏就可以写成
#define weakify(...) (rac_weakify_##metamacro_argcount(__VA_ARGS__))(__VA_ARGS__)
而RAC为了区分在这类的宏在前面加个@,其实就是
#define weakify(...) autoreleasePool{} (rac_weakify_##metamacro_argcount(__VA_ARGS__))(__VA_ARGS__)
其中SEP
就是宏定义空字符,用来分开宏定义字符连接
关键点
假设定义#define macro1 左(
...
) 右(__VA_ARGS__
)
关键点:宏中的...=> __VA_ARGS__
从左到右是全映射
而宏中右部分的__VA_ARGS__
映射到另一个宏时,是逐个映射到变量,只有映射不到的时候,或者有剩余没有映射到的参数才映射到...