RACBlockTrampoline.m 5.6 KB

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