ReactiveCocoa之RAC宏展开解析【iOS源码阅读】

RAC() 可以将Signal发出事件的值赋值给某个对象的某个属性,其参数为对象名和属性名,平时用到的宏如:

RAC(TARGET, [KEYPATH, [NIL_VALUE]])

版本:ReactiveCocoa-2.3.1

RAC宏展开解析


以下通过分析宏顺序展开分析依次得到的结果,并得到最终代码

【这个宏封装的牛逼,愣是看了好久!!!】,详细如下:

一. RAC(TARGET, 2)

**  PA: RAC_(TARGET,2,nil)
**  PB: RAC_(TARGET,2)
  1. metamacro_if_eq(1,metamacro_argcount(TARGET, 2)) (PA) (PB)
  2. 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)
  3. 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)
  4. 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)
  5. metamacro_if_eq(1,metamacro_head(2, 1)) (PA) (PB)
  6. metamacro_if_eq(1,metamacro_head_(2, 1, 0)) (PA) (PB)
  7. metamacro_if_eq(1,2) (PA) (PB)#所以metamacro_argcount就是参数的个数
  8. metamacro_concat(metamacro_if_eq,1)(2) (PA) (PB)
  9. metamacro_if_eq1(2) (PA) (PB)
  10. metamacro_if_eq0(metamacro_dec(2) (PA) (PB)
  11. 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)
  12. 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)
  13. 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)
  14. 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)
  15. metamacro_if_eq0(1) (PA) (PB)
  16. metamacro_concat(metamacro_if_eq0_,1) (PA) (PB)
  17. metamacro_if_eq0_1 (PA) (PB)
  18. metamacro_expand_ (PA) (PB)#PA被metamacro_expand_带走了,就剩下PB
  19. 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__))
  1. metamacro_if_eq(1,metamacro_argcount(TARGET)) (PA) (PB)
  2. 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)
  3. metamacro_if_eq(1,metamacro_head(1)) (PA) (PB)
  4. metamacro_if_eq1(1) (PA) (PB)
  5. metamacro_if_eq0(metamacro_dec(1)) (PA) (PB)
  6. 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)
  7. 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)
  8. metamacro_if_eq0(0) (PA) (PB)
  9. metamacro_if_eq0_0 (PA) (PB)
  10. (PA) metamacro_consume_ (PB)
  11. PA
=>RAC_(TARGET, __VA_ARGS__, nil)

三. RAC(TARGET, 2,3,4)

有了以上基础,这里简要中介展开过程,直接讲重点!
**  PA: RAC_(TARGET,__VA_ARGS__,nil)
**  PB: RAC_(TARGET,__VA_ARGS__)
  1. metamacro_if_eq(1,4) (PA) (PB)#所以参数的个数4
  2. metamacro_if_eq0_3 (PA) (PB)#metamacro_if_eq0_1~metamacro_if_eq0_20定义一样,所以还是PB
  3.         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_


你可能感兴趣的:(iOS开发)