【发布时间】:2012-02-10 18:32:25
【问题描述】:
我正在尝试通过以下方式在 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:。第二个很容易,但第一个是问题的全部内容。
我们应该知道代理对象的类以便能够提供签名,但是另一个代理初始化的调用不提供有关返回对象类的信息。有没有办法使用 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 一起使用可能有风险!)。
【问题讨论】:
标签: objective-c runtime objective-c-runtime