Calling a selector with unknown number of arguments using reflection / introspection

后端 未结 4 1587
-上瘾入骨i
-上瘾入骨i 2020-12-16 07:39

Lately I wrote an application in java (for android) which used reflection to invoke methods of some objects. The argument number and type was unknown, meaning, I had a unifi

4条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-16 07:47

    I modified @JustSid answer and added more validation, nil argument support, changed it to an Obj-C NSObject category method, and add -performSelectorIfAvailable: helper methods for easier use. Please enjoy! :)

    #import 
    
    @implementation NSObject (performSelectorIfAvailable)
    
    // Invokes a selector with an arbitrary number of arguments.
    // Non responding selector or too few arguments will make this method do nothing.
    // You can pass [NSNull null] objects for nil arguments.
    - (void)invokeSelector:(SEL)selector arguments:(NSArray*)arguments {
        if (![self respondsToSelector:selector]) return; // selector not found
    
        // From -numberOfArguments doc,
        // "There are always at least 2 arguments, because an NSMethodSignature object includes the hidden arguments self and _cmd, which are the first two arguments passed to every method implementation."
        NSMethodSignature *signature = [self methodSignatureForSelector:selector];
        int numSelArgs = [signature numberOfArguments] - 2;
        if (numSelArgs > [arguments count]) return; // not enough arguments in the array
    
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
        [invocation setTarget:self];
        [invocation setSelector:selector];
    
        for(int i=0; i < numSelArgs; i++) {
            id arg = [arguments objectAtIndex:i];
            if (![arg isKindOfClass:[NSNull class]]) {
                [invocation setArgument:&arg atIndex:i + 2];
            }
        }
        [invocation invoke]; // Invoke the selector
    }
    

提交回复
热议问题