5

所以基本上我正在使用 window.location="myobj:mymethod:myarg:myotherarg" 实现在 objc 中处理 JavaScript 调用的典型方法,但是,我想知道是否有一种方法可以将参数数组应用于方法,类似于在 JavaScript 中的操作。

通常我一直在做

-(void) mymethod:(NSArray*) arr{
    //method knows how many arguments it takes and what they mean at each index
}

我宁愿这样做:

-(void) mymethod:(NSString*) myarg myOtherArg: (NSString*) myotherarg{
    //do stuff
}

并有这样的方法:

+(void) callMethod:(NSString*)selectorName withArgs: (NSArray*)args onObject:(id) obj{
    //implementation
}
[JEHelpers callMethod:selector withArgs:someArrayOfArgs onObject:myapp]

这可能吗?

4

4 回答 4

2

我不确定我是否完全理解这个问题(我不太了解 JavaScript)。但是,您可以使用 NSInvocation 向任何对象发送任意消息。像这样的东西:

+(void) callMethod:(NSString*)selectorName withArgs: (NSArray*)args onObject:(id) obj
{
    SEL selector = NSSelectorFromString(selectorName);
    if (![obj respondsToSelector:selector]) {
        // Object doesn't respond to selector, so do something else/handle the error
    }
    NSMethodSignature *methodSignature = [obj methodSignatureForSelector:selector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
    [invocation setTarget:obj];
    [invocation setSelector:selector];
    for (NSUInteger i=0; i<[args count]; i++) {
        id argument = [args objectAtIndex:i];
        [invocation setArgument:&argument atIndex:i+2]; // Arg 0 is self, arg 1 is _cmd
    }
    id result;
    [invocation setReturnValue:&result];
    [invocation invoke];
}
于 2012-05-11T15:12:38.190 回答
2

如果您知道任何方法都不会接受两个以上的参数,那么您可以使用performSelector:withObject:withObject:来执行这些调用。如果该方法接受的参数少于两个,则未使用的withObject:字段将被忽略。

+ (id)callMethod:(NSString *)selectorName withArgs:(NSArray *)args onObject:(id)obj {
    id arg1 = nil, arg2 = nil;
    if([args count]) {
        arg1 = [args objectAtIndex:0];
        if([args count] > 1])
           arg2 = [args objectAtIndex:1];
    }
    return [obj performSelector:NSSelectorFromString(selectorName)
                     withObject:arg1 withObject:arg2];
}

如果可能有两个以上的参数,则必须使用NSInvocation. 此类允许您通过传递各种参数并定义选择器和对象来构造消息,然后发送消息并获取结果。

+ (id)callMethod:(NSString *)selectorName withArgs:(NSArray *)args onObject:(id)obj {
    SEL sel = NSSelectorFromString(selectorName);
    NSMethodSignature *signature = [obj methodSignatureForSelector:sel];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setSelector:sel];
    [invocation setTarget:obj];
    NSUInteger index = 2;
    for(id arg in args) {
        [invocation setArgument:&arg atIndex:index];
        ++index;
    }
    id result;
    [invocation setReturnValue:&result];
    [invocation invoke];
    return result;
}
于 2012-05-11T15:07:08.673 回答
1

您可能想查看 NSInvocation。具体来说,您想使用 selectorName 的方法签名 (NSObject -methodSignatureForSelector:) 构建一个 NSInvocation,然后设置选择器、目标和参数。请记住:您应该检查参数类型(NSMethodSignature -getArgumentTypeAtIndex:,是否等于'@'),并且您传递的参数从 2 开始索引(因为 0 和 1 是对象的自身和方法选择器)。

顺便说一句,我并不是说这是个好主意;很少有情况需要这种方法。

于 2012-05-11T15:13:49.080 回答
0

这有点笨拙,但有可能:

- (id)method:(NSString *)arg1, ... {
  va_list args;
  va_start(args, arg1);
  for (NSString *a = arg1; a!= nil; a= va_arg(args, NSString*)) {
    // do stuff
  }
}

通常arg1是定义数据类型和额外参数数量的字符串。

你会这样称呼它:

[self method:@"5", @"4", @"3", @"2", @"1"];

对于大多数目的,您的数组方法可能更清晰。

于 2012-05-11T15:22:30.083 回答