0

Is there any method like this:

- (id)performSelector:(SEL)selector withParameters:(NSArray *)parameters;

and I can invoke a obj-c message like this:

// invoke a message with 3 parameters
[obj performSelector:@selector(evaluate:name:animate:) withParameters:@[@1, @"test", @YES]];

// invoke a message with 1 parameter which is an array containing 3 components.
[NSArray performSelector:@selector(arrayWithArray:) withParameters:@[@[@1, @"test", @YES]]];

If there is no such method like this. How can I implement this with Obj-C runtime? Is it impossible?

Xaree Lee
  • 3,188
  • 3
  • 34
  • 55
  • @MichaelDautermann no answer in that question provide a way that takes an array as arguments. – Bryan Chen Mar 04 '14 at 04:15
  • ummm, @BryanChen; my answer in the duplicate question *specifically shows* how to use an array in the arguments. – Michael Dautermann Mar 04 '14 at 04:29
  • 2
    @MichaelDautermann well, either you or me misunderstand this question. I thought OP is asking a way to invoke `someMethod:withArg:andArg:andArg:` with arguments packed within an array. not pass an array to `someMethodTakesArray:` – Bryan Chen Mar 04 '14 at 04:32
  • I agree with Bryan here; Michael's answer doesn't do precisely what's being asked for, [but valvoline's does](http://stackoverflow.com/a/15761474/). – jscs Mar 04 '14 at 04:42

1 Answers1

2

Use NSInvocation

- (id)performSelector:(SEL)selector withParameters:(NSArray *)parameters
{
    NSMethodSignature *signature  = [self methodSignatureForSelector:selector];
    NSInvocation      *invocation = [NSInvocation invocationWithMethodSignature:signature];

    [invocation setTarget:self];       
    [invocation setSelector:selector];            
    for (int i = 0; i < parameters.count; ++i)
    {
        id para = parameters[i];
        [invocation setArgument:&para atIndex:2+i];  
    }

    [invocation invoke];

    id ret;
    [invocation getReturnValue:&ret];
    return ret;

}

Note: this implementation only works if the invoked method takes ObjC objects as arguments and return an object. i.e. it won't work for something takes int or return double.

If you want it works for primitive types/struct, you have to check NSMethodSignature for arguments type and convert object to that type then pass it to setArgument:atIndex:.

Read this question for more detailed ansowers

Community
  • 1
  • 1
Bryan Chen
  • 45,816
  • 18
  • 112
  • 143