getArgument of NSInvocation of current method always returns null

1.9k views Asked by At

I want to get the name of the arguments of the current function I am in so that I can prepare loading that object from the filesystem if it's not present on the current instance. (for instance if [foo dictTest] is not available I want to load it's prior saved plist version into exactly that ivar)

I want to find the file by providing the ivar name that I provided as an argument to the current function.

This is the function code:

-(NSDictionary*)getCachedDictionary:(NSDictionary*)dict{

    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:_cmd]];
    NSString * firstArgument = nil;
    [invocation getArgument:&firstArgument atIndex:2];
    NSLog(@"Trying to get the objects ivar %@",firstArgument);

    // right now during testing return nil
    return nil;
   }

As soon as the code reaches the NSLog I am getting a null value from firstArgument.

Why is that? Could it be possible that I would have to wait for the complete invocation of that current method I am in or is it actually better to create a proxy function that implicitly calls my class method via an invocation that eats the ivar name provided by setArgument so that I can use that argument string like I want?

Thanks a lot in advance!

P.S.: In this particular example I do not want to use KVC to identify the ivar and return it.

2

There are 2 answers

1
Dave DeLong On BEST ANSWER

You've misunderstood the NSInvocation API. +[NSInvocation invocationWithMethodSignature:] creates a new NSInvocation that is keyed to accept arguments of the types defined by the method signature. It does not return an NSInvocation that corresponds to the current method invocation. This is pretty easy to see why:

- (void)doBar:(id)bip {
  NSLog(@"hi there!")
}

- (void)doFoo {
  NSMethodSignature *sig = [self methodSignatureForSelector:@selector(doBar:)];
  NSInvocation *i = [NSInvocation invocationWithMethodSignature:sig];
}

When you create the invocation in doFoo for the doBar: method, it's obvious to see that the arguments must be empty, because doBar: hasn't been executed, and thus there is no argument. Changing @selector(doBar:) to _cmd wouldn't magically change anything.

So the next question: is there a way to get an NSInvocation for the current method invocation? Not that I know of. NSInvocation is an extremely complicated class, and constructing one from the current method would be a nightmare.

I strongly suggest finding a different approach to do whatever it is you want to do.

0
Michael Utech On

Even though the question is old and answered, here is a link that provides an easy and very elegant way to create an invocation instance for any selector/method that is known at compile time:

http://www.cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html