按顺序射击方法

时间:2014-05-08 14:38:12

标签: ios cocoa methods nsinvocation

我有一系列方法,我必须按顺序触发。每个方法都返回一个BOOL。像

这样的东西
- (BOOL) oneMethod;

方法名称位于

之类的数组上
#define TESTS  @[         \
    @"averageNotOK:",     \
    @"numbersOverRange:", \
    @"numbersUnderRange:",\
    @"numbersForbidden:", \
    // ... etc etc
    @"numbersNotOnCurve:"]

方法在循环中运行。像

这样的东西
- (BOOL) numbersPassedAllTests:(NSArray *)numbers {

  NSInteger count = [TESTS count];

  for (int i=0; i<count; i++) {

        NSString *aMethodName = TESTS[i];

        SEL selector = NSSelectorFromString(aMethodName);

        BOOL failed = NO;

        NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];

        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
        [invocation setSelector:selector];
        [invocation setTarget:self];
        [invocation setArgument:&numbers atIndex:2];
        [invocation invoke];


        [invocation getReturnValue:&failed];

        if (failed) {
          return NO;
        }
  }
  return YES;

}

有没有办法在不使用NSInvocation的情况下运行这些方法?

是的,我需要一个字符串数组(不是选择器数组)的方法,因为我需要在其他上下文中使用它们的名字。我知道我不能使用performSelector,因为它返回void,我需要一些东西来返回BOOL。是的,我知道performSelector的扩展,它返回任何东西,但它使用NSInvocation,我试图在不使用NSInvocation的情况下发现另一种方法。

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

我找到了最佳答案here

答案是用这个代替整个事情:

#import <objc/message.h>
- (BOOL) numbersPassedAllTests:(NSArray *)numbers {

  NSInteger count = [TESTS count];

  for (int i=0; i<count; i++) {

        NSString *aMethodName = TESTS[i];

        SEL selector = NSSelectorFromString(aMethodName);

        BOOL (*BOOLMsgSend)(id, SEL, id) = (BOOL (*)(id, SEL, id)) objc_msgSend;
        BOOL failed = BOOLMsgSend(self, selector, numbers);

        if (failed) {
          return NO;
        }
  }
  return YES;

}

简单,漂亮,在我的测试中至少快30%。

答案 1 :(得分:-2)

您的另一个选择是:

[self performSelector:selector withObject:numbers];

您需要将结果存储在某处,例如将属性添加到当前对象:

@property (nonatomic, assign) BOOL lastTestResult;

让每个测试都设置好,然后在performSelector之后进行检查。

但我怀疑这确实会有所不同。看起来你正在做某种学术性的事情。如果调用这些调用的性能确实很重要,那么考虑只使它们成为C函数并使用函数指针数组。