Is it possible to pass a method as an argument in Objective-C?
Asked Answered
M

3

23

I have a method that varies by a single method call inside, and I'd like to pass the method/signature of the method that it varies by as an argument... is this possible in Objective C or is that too much to hope for?

Minier answered 6/2, 2009 at 8:54 Comment(0)
U
27

NSInvocation is a class for wrapping up a method calls in an object. You can set a selector (method signature), set arguments by index. You can then set a target and call invoke to trigger the call, or leave the target unset and use invokeWithTarget: in a loop of some sort to call this on many objects.

I think it works a little like this:

NSInvocation *inv = [[NSInvocation alloc] init];
[inv setSelector:@selector(foo:bar:)];
[inv setArgument:123 atIndex:0];
[inv setArgument:456 atIndex:1];

for (MyClass *myObj in myObjects) {
  [inv invokeWithTarget:myObj];
}

Or if you dont want to pass invocation objects into this method you can use the SEL type to accept a selector (method signature).

-(void)fooWithMethod:(SEL)selector;

Then assign the selector to an invocation object in order to call it on objects.

Unlade answered 6/2, 2009 at 9:12 Comment(2)
I just tried this and was unable to get it to work without first setting a method signature like this: NSMethodSignature* sig = [self methodSignatureForSelector:@selector(foo:bar:)]; NSInvocation *inv = [NSInvocation invocationWithMethodSignature:sig]; From there it should work.Forsworn
Also, be sure to start argument index at 2: Indices 0 and 1 indicate the hidden arguments self and _cmd, respectively; you should set these values directly with the target and selector properties. Use indices 2 and greater for the arguments normally passed in a message. - sourceForsworn
R
10

Or if you're using the fooWithMethod:(SEL)selector approach, just do [myObject performSelector:selector] on it, if it has no other arguments.

See NSObject for details.

Rozanne answered 8/2, 2009 at 6:5 Comment(0)
P
3

As said before you can pass the selector of the method you want to call. Using a selector there are different ways to actually call the method:

  1. using NSObjects performSelector:, performSelector:withObject: and performSelector:withObject:withObject: methods
  2. using a NSInvocation object
  3. or directly using objc_msgSend or objc_msgSend_stret
  4. using the IMP of that method which you can get using methodForSelector:

Which one to use really depends on the situation. If the performance is not critical I’d go ahead with 1 if you need to pass in 0, 1 or 2 objects. If the performSelector:... methods don’t match I’d go with 2 or 3. Since setting up an NSInvocation object requires a lot of boilerplate code I prefer 3, but I guess that’s a matter of personal choice, unless there are performance issues.

If the performance of those method calls does matter I’d use 3 or 4. 3 should be faster unless you can cache the IMPs. But depending on your code this may not be feasible or doesn’t really help. So here you must profile the code and see which one is better for you.

Proofread answered 28/9, 2010 at 10:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.