Search code examples
iosobjective-cnsinvocation

NSInvocation with primitive using getReturnValue


We have the following method, which works for objects. It takes a method on an object and places the result in returnValueContainer:

+ (void)invokePrivateMethod:(SEL)selector returnValueContainer:(NSObject **)returnValueContainer onObject:(NSObject *)object {
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[object class] instanceMethodSignatureForSelector:selector]];
    [invocation setSelector:selector];
    [invocation setTarget:object];
    [invocation invoke];
    [invocation getReturnValue:returnValueContainer];
}

Is it possible to modify this somehow so that we can return primitives (e.g. NSInteger) as well as objects from getReturnValue?

Background: we are trying to access a private primitive property on a class for unit tests.


Solution

  • Well if you wanted to do it with int, it would be enough to simply change it to returnValueContainer:(int *)returnValueContainer. If you want it to work for all types, you can just do returnValueContainer:(void *)returnValueContainer and let the caller pass in a pointer to the correct type.

    (By the way, what you are doing with NSObject ** is not correct in ARC. A parameter of type NSObject ** implicitly means NSObject * __autoreleasing *. But the correct type should be NSObject * __unsafe_unretained * because getReturnValue: simply treats the buffer pointed to as a plain byte buffer without knowing anything about memory management. It does not retain and autorelease it as it should for an __autorelease type. In most cases it won't make a difference (and the method that was invoked potentially autoreleased it anyway), there are cases where it would matter.)