2

Let's say I have the following method:

 -(void)methodWithVar1:(NSString*)var1 var2:(NSString*)var2;

Now of course I can access var1 and var2 within methodWithVar1:var2: by using the variable names directly. But what I'd like to do is something like methodArgs[0] and methodArgs[1] to access the variables.

Is there a way to do this? I've looked at runtime.h but can't see anything that helps.

Why do I want to do this?

In certain circumstances, when a method is called, I want to prevent the method executing, but allow it to execute at another moment in time. I'm doing this by creating an NSInvocation object that allows me to 're-call' the method when I would prefer it. However, NSInvocation requires that I call setArgument:atIndex:, which I have to do manually. If the method every changes, then the population of NSInvocation needs to be updated. I want to avoid updating it manually and have a generic way of doing it.

Example

-(void)methodWithVar1:(NSString*)var1 var2:(NSString*)var2{

    if (someCheckToSeeIfICannotRun) {

        NSMethodSignature * methodSignature = 
        [self.class instanceMethodSignatureForSelector:_cmd];

        KWInvocation * invocation = 
        [KWInvocation invocationWithMethodSignature:methodSignature];

        [invocation.invocation setTarget:self];
        [invocation.invocation setSelector:_cmd];
        [invocation.invocation setArgument:&var1 atIndex:2];// This and
        [invocation.invocation setArgument:&var2 atIndex:3];// this, I would prefer to make generic
        [invocation.invocation retainArguments];
        //
        // Store invocation somewhere so I can call it later...
        //
    }
    else {
        // Let the method run as normal
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Vamos
  • 2,701
  • 2
  • 24
  • 37
  • 4
    Why do you want to do this? – JoeFryer Mar 05 '14 at 09:30
  • @JoeFryer I need to cache a call to a method via NSInvocation, but in order to make something generic that fills the NSInvocation with var1 and var2 I need to do this. If a developer ever changes the method by either adding or removing variables, then the NSInvocation part needs updating, I want to avoid having to manually update it. – Vamos Mar 05 '14 at 09:39
  • 2
    Hmmm ok. You might find this question interesting: [link](http://stackoverflow.com/questions/8022134/get-arguments-of-objective-c-method-by-index). And this one: [link](http://stackoverflow.com/questions/14645659/index-based-fetching-of-objective-c-argument-values). – JoeFryer Mar 05 '14 at 09:59

1 Answers1

1

I think this can help you:

#import <objc/runtime.h>

void logArguments(const id* selfPtr)
{
    id obj = *selfPtr;
    SEL sel = *(SEL*)(void*)(--selfPtr);

    Method m  = class_getInstanceMethod([obj class], sel);

    for (unsigned int cnt = method_getNumberOfArguments(m) - 2; 0 != cnt; --cnt)
    {
        NSLog(@"arg: %@", *(--selfPtr));
    }
}

You can call logArguments(&self); in any method, but there is one restriction: all arguments should be objective-c objects.

Cy-4AH
  • 4,370
  • 2
  • 15
  • 22