使用反射/内省调用具有未知数量参数的选择器

MBy*_*ByD 5 reflection introspection objective-c ios

最近我在java(for android)中编写了一个应用程序,它使用反射来调用某些对象的方法.参数号和类型是未知的,这意味着,我有一个统一的机制,它接收一个对象名,方法名和参数数组(使用JSON),并使用参数数组(Object [])调用指定对象上的指定方法充满了所需类型的参数).

现在我需要为iOS实现相同的功能,当我知道选择器期望的参数数量时,我能够调用选择器:

SEL selector = NSSelectorFromString(@"FooWithOneArg");
[view performSelectorInBackground:selector withObject:someArg];
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过使用获得选择器接收的参数数量

int numberOfArguments = method_getNumberOfArguments(selector);
Run Code Online (Sandbox Code Playgroud)

但有没有办法像这样进行通用调用:

[someObject performSelector:selector withObject:arrayOfObjects]
Run Code Online (Sandbox Code Playgroud)

这几乎与Java相当

someMethod.invoke(someObject, argumentsArray[]);
Run Code Online (Sandbox Code Playgroud)

我想根据选择器获取的参数数量来避免切换情况.

对不起,我只是想尽可能清楚地提出问题.

Jus*_*Sid 12

这个小功能应该可以做到,但并不完美,但它为您提供了一个起点:

void invokeSelector(id object, SEL selector, NSArray *arguments)
{
    Method method = class_getInstanceMethod([object class], selector);
    int argumentCount = method_getNumberOfArguments(method);

    if(argumentCount > [arguments count])
        return; // Not enough arguments in the array

    NSMethodSignature *signature = [object methodSignatureForSelector:selector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setTarget:object];
    [invocation setSelector:selector];

    for(int i=0; i<[arguments count]; i++)
    {
        id arg = [arguments objectAtIndex:i];
        [invocation setArgument:&arg atIndex:i+2]; // The first two arguments are the hidden arguments self and _cmd
    }

    [invocation invoke]; // Invoke the selector
}
Run Code Online (Sandbox Code Playgroud)

  • 在类对象上使用时它不起作用,因为在类对象上调用`class`会调用`+ class`,它只返回类对象本身,而不是它的类.无论如何前两行是不必要的,因为你可以从`[signature numberOfArguments]获得`argumentCount`. (4认同)