3

I know that objective-c methods are actually c function, and that the first two arguments are self and _cmd. I'm trying to get the remaining arguments as an array (including or excluding, self and _cmd)

For example:

-(void)someMethod:(id)firstArg withObject:(id)secondArg andObject:(id)thirdArg {
     //then something like:
     args[0] //corresponds to self
     args[1] //corresponds to _cmd
     args[2] //corresponds to firstArg
     args[3] //corresponds to secondArg
     args[3] //corresponds to thirdArg
     //or just start from firstArg being the 0th item in the index (skipping out self and _cmd)
}

What I'm trying to do is something like:

[self doOtherMethod:@selector(otherMethod:withObject:andObject:) withObjects:args];

So how can I get an array (c array or even NSArray) of the arguments passed to the method, so that I can pass them on or enumerate through them?

EDIT: I want to do this with existing methods, e.g. delegate methods that I can't change.

Jonathan.
  • 53,997
  • 54
  • 186
  • 290

3 Answers3

4

Use NSInvocation; it can encapsulate a nearly arbitrary set of arguments, a selector and a target which can then be invoked later in a straightforward manner.

Alternatively, use blocks. You can encapsulate the call inside of a block, capturing whatever state you need while passing the rest in as arguments.

What you are trying to do is generally indication of design/architecture issues. You shouldn't need to do this.

However, there are certainly cases where it is required for any number of reasons (oft contractual -- been there, done that, know exactly how a contract can dictate the need for awful coding practices).


but can it also access the arguments of the current method?

"Sort of."

It isn't clear what you are asking. If the "current method" isn't one you implemented, then there is very little you can do (short of swizzling or other runtime games that really should never, ever, be used).

If it is one you've implemented, the just use the arguments. You can encode them in an NSInvocation if you want to delayed execution (or a block).

NSInvocation is used to grab arguments in a specific case; when implementing method forwarding, in particular. But that seems unrelated to what you are trying to do.

bbum
  • 162,346
  • 23
  • 271
  • 359
  • 2
    I know an NSInvocation can be used to send a message (/call a method), but can it also access the arguments of the current method? – Jonathan. Nov 05 '11 at 18:22
1

The mechanism for argument-passing is architecture-dependent, and may involve passing values in registers, on the stack, or both. Trying to ferret out the list of arguments dynamically for anything other than debugging purposes is probably not a good idea, and certainly not portable.

Here's an article that I think would be a great starting point for gaining more insight into how arguments are passed: http://en.wikipedia.org/wiki/Calling_convention

jlehr
  • 15,557
  • 5
  • 43
  • 45
0

Try creating a function that takes in NSArray of those args. You can do it without passing in self or _cmd.

- (void)serverRespondedWithJSONObjects:(NSArray *)objects {
  NSMutableArray *objects = [NSMutableArray array];
  for (NSDictionary *dictonary in objects) {
    SomeObject *object = [[[SomeObject alloc] init] autorelease];
    object.name = [dictionary valueForKey:@"name"];
    [objects addObject:object];
  }
  [self doSomethingWithArgs:objects];
}

- (void)doSomethingWithArgs:(NSArray *)args {

  for (SomeClass *someObject in args) {
    //do something interesting with someObject.
  }

}
Eugene
  • 10,006
  • 4
  • 37
  • 55