RACBlockTrampoline.m 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. //
  2. // RACBlockTrampoline.m
  3. // ReactiveObjC
  4. //
  5. // Created by Josh Abernathy on 10/21/12.
  6. // Copyright (c) 2012 GitHub, Inc. All rights reserved.
  7. //
  8. #import "RACBlockTrampoline.h"
  9. #import "RACTuple.h"
  10. @interface RACBlockTrampoline ()
  11. @property (nonatomic, readonly, copy) id block;
  12. @end
  13. @implementation RACBlockTrampoline
  14. #pragma mark API
  15. - (instancetype)initWithBlock:(id)block {
  16. self = [super init];
  17. _block = [block copy];
  18. return self;
  19. }
  20. + (id)invokeBlock:(id)block withArguments:(RACTuple *)arguments {
  21. NSCParameterAssert(block != NULL);
  22. RACBlockTrampoline *trampoline = [(RACBlockTrampoline *)[self alloc] initWithBlock:block];
  23. return [trampoline invokeWithArguments:arguments];
  24. }
  25. - (id)invokeWithArguments:(RACTuple *)arguments {
  26. SEL selector = [self selectorForArgumentCount:arguments.count];
  27. NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:selector]];
  28. invocation.selector = selector;
  29. invocation.target = self;
  30. for (NSUInteger i = 0; i < arguments.count; i++) {
  31. id arg = arguments[i];
  32. NSInteger argIndex = (NSInteger)(i + 2);
  33. [invocation setArgument:&arg atIndex:argIndex];
  34. }
  35. [invocation invoke];
  36. __unsafe_unretained id returnVal;
  37. [invocation getReturnValue:&returnVal];
  38. return returnVal;
  39. }
  40. - (SEL)selectorForArgumentCount:(NSUInteger)count {
  41. NSCParameterAssert(count > 0);
  42. switch (count) {
  43. case 0: return NULL;
  44. case 1: return @selector(performWith:);
  45. case 2: return @selector(performWith::);
  46. case 3: return @selector(performWith:::);
  47. case 4: return @selector(performWith::::);
  48. case 5: return @selector(performWith:::::);
  49. case 6: return @selector(performWith::::::);
  50. case 7: return @selector(performWith:::::::);
  51. case 8: return @selector(performWith::::::::);
  52. case 9: return @selector(performWith:::::::::);
  53. case 10: return @selector(performWith::::::::::);
  54. case 11: return @selector(performWith:::::::::::);
  55. case 12: return @selector(performWith::::::::::::);
  56. case 13: return @selector(performWith:::::::::::::);
  57. case 14: return @selector(performWith::::::::::::::);
  58. case 15: return @selector(performWith:::::::::::::::);
  59. }
  60. NSCAssert(NO, @"The argument count is too damn high! Only blocks of up to 15 arguments are currently supported.");
  61. return NULL;
  62. }
  63. - (id)performWith:(id)obj1 {
  64. id (^block)(id) = self.block;
  65. return block(obj1);
  66. }
  67. - (id)performWith:(id)obj1 :(id)obj2 {
  68. id (^block)(id, id) = self.block;
  69. return block(obj1, obj2);
  70. }
  71. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 {
  72. id (^block)(id, id, id) = self.block;
  73. return block(obj1, obj2, obj3);
  74. }
  75. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 {
  76. id (^block)(id, id, id, id) = self.block;
  77. return block(obj1, obj2, obj3, obj4);
  78. }
  79. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 {
  80. id (^block)(id, id, id, id, id) = self.block;
  81. return block(obj1, obj2, obj3, obj4, obj5);
  82. }
  83. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 {
  84. id (^block)(id, id, id, id, id, id) = self.block;
  85. return block(obj1, obj2, obj3, obj4, obj5, obj6);
  86. }
  87. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 {
  88. id (^block)(id, id, id, id, id, id, id) = self.block;
  89. return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7);
  90. }
  91. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 {
  92. id (^block)(id, id, id, id, id, id, id, id) = self.block;
  93. return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8);
  94. }
  95. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 {
  96. id (^block)(id, id, id, id, id, id, id, id, id) = self.block;
  97. return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9);
  98. }
  99. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 {
  100. id (^block)(id, id, id, id, id, id, id, id, id, id) = self.block;
  101. return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10);
  102. }
  103. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 {
  104. id (^block)(id, id, id, id, id, id, id, id, id, id, id) = self.block;
  105. return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11);
  106. }
  107. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 {
  108. id (^block)(id, id, id, id, id, id, id, id, id, id, id, id) = self.block;
  109. return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12);
  110. }
  111. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 :(id)obj13 {
  112. id (^block)(id, id, id, id, id, id, id, id, id, id, id, id, id) = self.block;
  113. return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13);
  114. }
  115. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 :(id)obj13 :(id)obj14 {
  116. id (^block)(id, id, id, id, id, id, id, id, id, id, id, id, id, id) = self.block;
  117. return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13, obj14);
  118. }
  119. - (id)performWith:(id)obj1 :(id)obj2 :(id)obj3 :(id)obj4 :(id)obj5 :(id)obj6 :(id)obj7 :(id)obj8 :(id)obj9 :(id)obj10 :(id)obj11 :(id)obj12 :(id)obj13 :(id)obj14 :(id)obj15 {
  120. id (^block)(id, id, id, id, id, id, id, id, id, id, id, id, id, id, id) = self.block;
  121. return block(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13, obj14, obj15);
  122. }
  123. @end