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

发布于 2025-01-05 04:00:34 字数 2645 浏览 4 评论 0原文

我试图通过以下方式在 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: 和forwardInitation:。第二个很简单,但第一个是问题的全部内容。

我们应该知道代理对象的类,以便能够提供签名,但初始化 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 一起使用它可能存在风险!)。

I'm trying to implement in Objective-C a proxy for an object in the following way:

- (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];
    }
}

Another proxy should construct the object from this invocation. But while the object is under construction we should be able to collect and store invocations to it to have a chance to process them after the object is constructed. To achieve this I should implement 2 methods: methodSignatureForSelector: and forwardInvocation:. The second is quite easy but the first is what the question is all about.

We should know the class of the proxified object to be able to provide signature but the invocation which anotherProxy is initialized with does not provide information about the returned object's class. Is there a way to obtain the class of the object which will be returned by the method using Apple's Objective-C runtime?

UPDATE:

I understand that the actual class of the returned object may be different but there may be the only class with which the method is declared. If method is declared as

 - (SomeClass*) someMethod;

in the interface I expect SomeClass to be obtained.

UPDATE:

Finally I've solved my problem. The solution is not elegant but it 'just works'.
I've wrote this method:

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;
}

This method returns signature for selector if it is not ambiguous and nil in other case.
Its main con is the fact that it does not support class/list of classes modification in runtime thus it can be used only if all classes are registered and code does not modify classes (potentially risky to use it with KVO!).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

红玫瑰 2025-01-12 04:00:34

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

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

Is there a way to obtain the class of the object which will be returned by the method using Apple's Objective-C runtime?

No - if a method returns a class-type, you can't know the actual - concrete - type before it has returned. With the concrete class-type being unknown, you can't find out what return type any of it's method may have.

此岸叶落 2025-01-12 04:00:34

下面是如何检查“instance”是否是一个 NSString

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

好不好?

Here's how to check if "instance" is an NSString

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

That good?

怼怹恏 2025-01-12 04:00:34

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

例如,对于对象 foo

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

You can get the actual name of the class of the object:

e.g. for an object foo

NSLog(@"foo is an object of class %@", NSStringFromClass([foo class]));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文