Objective C - 获取方法的参数类型?

时间:2014-02-07 23:52:41

标签: objective-c objective-c-runtime

在运行时,我需要能够获取方法的参数类型。以下是打印的内容:

我已经读过其他线程,在运行时,objective c将传递给方法的所有对象视为id的参数。如果这种方法在读取参数类型的方法上没有任何其他建议吗?

日志

2014-02-07 15:47:08.962 OCInjection[55727:70b] @
2014-02-07 15:47:08.964 OCInjection[55727:70b] :

代码

Class class = NSClassFromString(injectionBinding);

unsigned int methodCount;
Method *methodList = class_copyMethodList(class, &methodCount);

for (int i = 0; i < methodCount; i++)
{
   Method method = methodList[i];
   SEL selector = method_getName(method);
   NSMethodSignature *signature = [class instanceMethodSignatureForSelector:selector];

   NSUInteger numberOfArguments = [signature numberOfArguments];

   for (int i=0 ; i<numberOfArguments ; i++)
   {
      NSString *type = [NSString stringWithUTF8String:[signature getArgumentTypeAtIndex:i]];
                    NSLog(type);
   }
}

2 个答案:

答案 0 :(得分:1)

根据 -getArgumentTypeAtIndex:Decode Class from @encoded type string

我认为没有方法可以获得“真正的”参数类型。

答案 1 :(得分:0)

似乎不可能这样做。我最终使用代理对象将消息发送到并捕获它。可能不是理想的方式,但我还没有找到更好的解决方案。

@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

用户如何使用它来定义方法参数

[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))];