在Objective-C中获取返回对象的类

时间:2012-02-10 18:32:25

标签: objective-c runtime objective-c-runtime

我正在尝试以下列方式在Objective-C中实现对象的代理:

- (NSMethodSignature*) methodSignatureForSelector:(SEL)sel
{
    return [_proxifiedObject methodSignatureForSelector:sel];
}

- (void) forwardInvocation:(NSInvocation *)invocation
{
    char returnType = invocation.methodSignature.methodReturnType[0];
    if(returnType == '@')
    {
        id anotherProxy = [[[MyProxy alloc] initWithInvocation:invocation] autorelease];
        [invocation setReturnValue:&anotherProxy];
    } else {
        invocation.target = _proxifiedObject;
        [invocation invoke];
    }
}

另一个代理应该从此调用构造对象。但是当对象正在构建时,我们应该能够收集并存储对它的调用,以便在构造对象之后有机会处理它们。为实现这一点,我应该实现2个方法:methodSignatureForSelector:和forwardInvocation:。第二个是相当容易的,但首先是问题的全部内容。

我们应该知道能够提供签名的代理对象的类,但是初始化anotherProxy的调用不提供有关返回的对象类的信息。有没有办法获取将使用Apple的Objective-C运行时方法返回的对象类?

更新

我理解返回对象的实际类可能不同,但可能只有声明该方法的类。如果方法声明为

 - (SomeClass*) someMethod;
接口中的

我希望得到SomeClass。

更新

最后我解决了我的问题。解决方案并不优雅,但它“正常”。 我写过这个方法:

static NSMutableDictionary* dictionarySelectorsToSignatures;

+ (NSMethodSignature*) methodSignatureForUnknownClassForSelector: (SEL) sel
{
    NSMethodSignature* candidate = [dictionarySelectorsToSignatures objectForKey:[NSNumber numberWithLongLong:(long long) sel]];
    if(candidate == nil)
    {
        int classesCount = objc_getClassList(NULL, 0);
        Class* classes = malloc(sizeof(Class) * classesCount);
        objc_getClassList(classes, classesCount);
        for(int i = 0; i < classesCount; i++)
        {
            if(class_getClassMethod(classes[i], @selector(instanceMethodSignatureForSelector:)) != NULL)
            {
                NSMethodSignature* signature = [classes[i] instanceMethodSignatureForSelector:sel];
                if(signature != nil)
                {
                    if(candidate != nil)
                    {
                        if(![candidate isEqual:signature])
                        {
                            return nil;
                        }
                    } else {
                        candidate = signature;
                    }
                }
            }
        }
        if(candidate != nil)
        {
            [dictionarySelectorsToSignatures setObject:candidate 
                                                forKey:[NSNumber numberWithLongLong:(long long)  sel]];
        }
    }
    return candidate;
}

如果选择器不是模糊的,则此方法返回选择符,而在其他情况下,返回nil。 它的主要缺点是它不支持在运行时修改类的类/列表,因此只有在所有类都被注册且代码不修改类时才能使用它(使用KVO时可能存在风险!)。

3 个答案:

答案 0 :(得分:2)

  

有没有办法获取将使用Apple的Objective-C运行时方法返回的对象类?

否 - 如果方法返回类类型,则在返回之前无法知道实际的具体类型。由于具体的类类型未知,您无法找出它的方法可能具有的返回类型。

答案 1 :(得分:0)

以下是检查“instance”是否为NSString

的方法
if ([instance isKindOfClass:[NSString class]]( {
  //do something
}

那好吗?

答案 2 :(得分:0)

您可以获取对象类的实际名称:

e.g。对象foo

NSLog(@"foo is an object of class %@", NSStringFromClass([foo class]));