我有一系列方法,我必须按顺序触发。每个方法都返回一个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的情况下发现另一种方法。
有什么想法吗?
答案 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函数并使用函数指针数组。