Richard
Richard

Reputation: 3296

Performing dynamic class method calls in Objective-C with more than two parameters

I have a method that dynamically creates new objects of different classes and want to be able to perform a selector on these classes as they are created. Using performSelector: withObject: would had worked but the methods have four arguments. I tried the following code using NSInvocation but got an error about it being an unrecognized selector.

NSInvocation *call = [NSInvocation invocationWithMethodSignature:[NSClassFromString(className) methodSignatureForSelector:@selector(packWithName:value:writer:forClass:)]];
[call setArgument:&arg1 atIndex:0];
[call setArgument:&arg2 atIndex:1];
[call setArgument:&arg3 atIndex:2];
[call setArgument:&arg4 atIndex:3];
call.target = NSClassFromString(className);
[call invoke];

It also produces the following log statement:

*** NSForwarding: warning: selector (0x8ed78d0) for message '[garbled random characters]'
does not match selector known to Objective C runtime (0x8b0cd30)-- abort

I also tried to create the NSInvocation using alloc/init and setting the @selector like this:

NSInvocation *call = [[NSInvocation alloc] init];
call.selector = @selector(nameofselector);

That however results in call being nil, so I guess that's not allowed.

Am I missing something regarding how NSInvocation works or is there a smarter way to do this?

Upvotes: 4

Views: 1584

Answers (2)

Aniket Kote
Aniket Kote

Reputation: 541

The Apple documentation just tell that the first argument (with indice 0) represent the target object (so the "self"). As the documentation explains you the first argument is set using the setTarget: method.

So you need to start indices from 2 onwards for using NSInvocation.(that means your code should be like)

NSInvocation *call = [NSInvocation invocationWithMethodSignature:[NSClassFromString(className) methodSignatureForSelector:@selector(packWithName:value:writer:forClass:)]];
[call setArgument:&arg1 atIndex:2];
[call setArgument:&arg2 atIndex:3];
[call setArgument:&arg3 atIndex:4];
[call setArgument:&arg4 atIndex:5];
call.target = NSClassFromString(className);
[call invoke];

Upvotes: 4

user529758
user529758

Reputation:

Arguments at index 0 and 1 are not the first two explicit arguments of the method call, but the implicit self and _cmd arguments. Use indices 2, 3, 4 and 5 instead.

Upvotes: 6

Related Questions