Objective C - Get argument types of a method?

寵の児 提交于 2019-12-06 12:04:34
Chen-Hai

According to -getArgumentTypeAtIndex: and Decode Class from @encoded type string

I think there is no method to get the "real" argument type.

Doesn't seem like it's possible to do this. I ended up using a proxy object to send the message to, and capture it. Probably not the ideal way, but I haven't found a better solution.

@interface DIContructorInjectorProxy()
@property (nonatomic, strong) id realObject;
@end

@implementation DIContructorInjectorProxy

#define Inject(x) [DIContructorInjectorProxy _injectMacro:x]

- (id)initWithClass:(Class)class
{
   self.realObject = [[class alloc] init];
}

+ (id)_injectMacro:(id)x
{
    if ([x isKindOfClass:NSClassFromString(@"Protocol")])
        return NSStringFromProtocol(x);
    else
        return NSStringFromClass(x);
}

- (id)withConstructor
{
    // Just making the method call for defining a constructor more readable by a call to this method first
    return self;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    NSMutableString *selectorName = [NSStringFromSelector(anInvocation.selector) mutableCopy];
    NSUInteger numberOfColonsInMethodName = [selectorName replaceOccurrencesOfString:@":"
                                                                           withString:@":"
                                                                              options:NSLiteralSearch
                                                                                range:NSMakeRange(0, selectorName.length)];

    [anInvocation retainArguments];
    NSMutableArray *argumentsPassedToSelector = [NSMutableArray array];

    for (int i=2 ; i<numberOfColonsInMethodName+2 ; i++)
    {
        NSString *argument;
        [anInvocation getArgument:&argument atIndex:i];
        [argumentsPassedToSelector addObject:[NSString stringWithFormat:@"%@", argument]];
    }

    // Store arguments somewhere

    return;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    return [self.realObject methodSignatureForSelector:aSelector];
}

@end

How the user uses this to define method arguments

[self bindProtocol:@protocol(DataStorage) toClass:[InMemoryDataStorage class]];

// withConstructor returns an appropriate proxy object
// Then when the init method is called, it calls forwardInvocation, 
// and from there I save all the info I need about the method and arguments
(void)[[[self bindProtocol:@protocol(GoogleClient) toClass:[GoogleClientEngine class]] withConstructor]
                initWithDataStorage:Inject(@protocol(DataStorage))];
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!