RAC() 可以将Signal发出事件的值赋值给某个对象的某个属性,其参数为对象名和属性名,平时用到的宏如:
RAC(TARGET, [KEYPATH, [NIL_VALUE]])
版本:ReactiveCocoa-2.3.1
RAC宏展开解析
以下通过分析宏顺序展开分析依次得到的结果,并得到最终代码
【这个宏封装的牛逼,愣是看了好久!!!】,详细如下:
一. RAC(TARGET, 2)
** PA:
RAC_(TARGET,2,nil)
** PB:
RAC_(TARGET,2)
- metamacro_if_eq(1,metamacro_argcount(TARGET, 2)) (PA) (PB)
- metamacro_if_eq(1,metamacro_at(20,TARGET, 2 , 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) (PA) (PB)
- metamacro_if_eq(1,metamacro_concat(metamacro_at,20)(TARGET, 2 , 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) (PA) (PB)
- metamacro_if_eq(1,metamacro_at20(TARGET, 2 , 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) (PA) (PB)
- metamacro_if_eq(1,metamacro_head(2, 1)) (PA) (PB)
- metamacro_if_eq(1,metamacro_head_(2, 1, 0)) (PA) (PB)
- metamacro_if_eq(1,2) (PA) (PB)#所以metamacro_argcount就是参数的个数
- metamacro_concat(metamacro_if_eq,1)(2) (PA) (PB)
- metamacro_if_eq1(2) (PA) (PB)
- metamacro_if_eq0(metamacro_dec(2) (PA) (PB)
- metamacro_if_eq0(metamacro_at(2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)) (PA) (PB)
- metamacro_if_eq0(metamacro_concat(metamacro_at,2)(-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)) (PA) (PB)
- metamacro_if_eq0(metamacro_at2(-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)) (PA) (PB)
- metamacro_if_eq0(metamacro_head(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)) (PA) (PB)
- metamacro_if_eq0(1) (PA) (PB)
- metamacro_concat(metamacro_if_eq0_,1) (PA) (PB)
- metamacro_if_eq0_1 (PA) (PB)
- metamacro_expand_ (PA) (PB)#PA被metamacro_expand_带走了,就剩下PB
- PB
=> RAC_(TARGET,2)
=>[[RACSubscriptingAssignmentTrampoline alloc] initWithTarget:(TARGET) nilValue:(NILVALUE)][@keypath(TARGET, 2)]
二. RAC(TARGET)
** PA:
(RAC_(TARGET, __VA_ARGS__, nil))
** PB:
(RAC_(TARGET, __VA_ARGS__))
- metamacro_if_eq(1,metamacro_argcount(TARGET)) (PA) (PB)
- metamacro_if_eq(1,metamacro_at20(TARGET, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) (PA) (PB)
- metamacro_if_eq(1,metamacro_head(1)) (PA) (PB)
- metamacro_if_eq1(1) (PA) (PB)
- metamacro_if_eq0(metamacro_dec(1)) (PA) (PB)
- metamacro_if_eq0(metamacro_at1(-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)) (PA) (PB)
- metamacro_if_eq0(metamacro_head(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)) (PA) (PB)
- metamacro_if_eq0(0) (PA) (PB)
- metamacro_if_eq0_0 (PA) (PB)
- (PA) metamacro_consume_ (PB)
- PA
=>RAC_(TARGET, __VA_ARGS__, nil)
三. RAC(TARGET, 2,3,4)
有了以上基础,这里简要中介展开过程,直接讲重点!
** PA:
RAC_(TARGET,__VA_ARGS__,nil)
** PB:
RAC_(TARGET,__VA_ARGS__)
- metamacro_if_eq(1,4) (PA) (PB)#所以参数的个数4
- metamacro_if_eq0_3 (PA) (PB)#metamacro_if_eq0_1~metamacro_if_eq0_20定义一样,所以还是PB
- PB
=>RAC_(TARGET,__VA_ARGS__)
总结
- 如果只有1个参数的,就调用RAC_(TARGET, __VA_ARGS__, nil)
- 如果有多个参数的,就调用RAC_(TARGET, __VA_ARGS__)
具体如下:
#define RAC_(TARGET, KEYPATH, NILVALUE) \
[[RACSubscriptingAssignmentTrampoline alloc] initWithTarget:(TARGET) nilValue:(NILVALUE)][@keypath(TARGET, KEYPATH)]
========================================
以上分析过程中参考的宏定义
========================================
#define metamacro_concat_(A, B) A ## B
#define metamacro_concat(A, B) \
metamacro_concat_(A, B)
#define metamacro_if_eq(A, B) \
metamacro_concat(metamacro_if_eq, A)(B)
#define metamacro_at(N, ...) \
metamacro_concat(metamacro_at, N)(__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)
#define RAC_(TARGET, KEYPATH, NILVALUE) \
[[RACSubscriptingAssignmentTrampoline alloc] initWithTarget:(TARGET) nilValue:(NILVALUE)][@keypath(TARGET, KEYPATH)]
#define RAC(TARGET, ...) \
metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__)) \
(RAC_(TARGET, __VA_ARGS__, nil)) \
(RAC_(TARGET, __VA_ARGS__))
#define metamacro_head_(FIRST, ...) FIRST
#define metamacro_head(...) \
metamacro_head_(__VA_ARGS__, 0)
#define metamacro_at1(_0, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at2(_0, _1, ...) metamacro_head(__VA_ARGS__)
#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__)
#define metamacro_if_eq0(VALUE) \
metamacro_concat(metamacro_if_eq0_, VALUE)
#define metamacro_dec(VAL) \
metamacro_at(VAL, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
#define metamacro_if_eq1(VALUE) metamacro_if_eq0(metamacro_dec(VALUE))
#define metamacro_expand_(...) __VA_ARGS__
#define metamacro_if_eq0_1(...) metamacro_expand_
#define metamacro_consume_(...)
#define metamacro_if_eq0_0(...) __VA_ARGS__ metamacro_consume_