Objective-C消息传递,巧妙地处理未知消息

时间:2009-02-27 00:11:18

标签: objective-c runtime messaging conceptual

有没有办法做一些类似于KVC但是使用消息名称作为密钥本身?例如,对象是否有一种方法可以响应所有消息而不是valueForKey:

例如,假设您有一个XML文档:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ...>
<employees>
  <employee>
    <name>Bill</name>
    <department>Accounting</department>
  </employee>
  <employee>
    <name>John</name>
    <department>Human Resources</department>
  </employee>
</employees>

除了使用已经可用的NSXMLDocument和co。之外,还有办法实现某种抽象,所以你可以这样做:

MyXML *xmlDoc = [[MyXML alloc] initWithContentsOfFile:@"test.xml"];

NSLog (@"%@", [[[xmlDoc employees] first] department]);

[[[xmlDoc employees] first] setDepartment:@"Management"];

我选择XML只是作为一个例子,但我想知道这是否可行,以及它是否涉及过于接近Objective-C运行时或者是否受运行时本身支持,以及如何我会去实现这样的东西。这纯粹是出于实验目的,我理解可能会有很大的性能成本。

修改
如果可能的话,我想避免像Cocoa这样的现有框架,并使用基础Objective-C对象Object

2 个答案:

答案 0 :(得分:3)

您需要实施forwardInvocation:methodSignatureForSelector:来处理无法识别的邮件。 NSObject引用中为described

编辑:维基百科有example如何为Object完成转发,基本上是通过实施forward:performv:

答案 1 :(得分:1)

感谢codelogic,我发现你需要为GCC的Objective-C运行时做的所有事情是:

#import <obc/Object.h>
#import <stdio.h>

@interface RespondsToEverything : Object {}
@end

@implementation RespondsToEverything
- (retval_t) forward:(SEL) sel :(arglist_t) argFrame
{
    fprintf (stderr, "Received: %s\n", get_sel_name (sel));
}
@end

int main (int argc, char *argv[])
{
    id test = [RespondsToEverything new];
    [test asdfasdfasdfasdf];
    [test zxcvzxcvzxcvzxcv];

    return 0;
}

输出结果为:

Received: asdfasdfasdfasdf
Received: zxcvzxcvzxcvzxcv

但是,当然,GCC抱怨它找不到asdfasdfasdfasdfzxcvzxcvzxcvzxcv的方法签名。没什么大不了的,它仍然表明这个概念是可行的。在Apple的运行时中,您可以使用sel_getName(sel)代替get_sel_name(sel)