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_


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章