Objective-C消息传递,智能处理未知消息

发布于 2024-07-14 05:01:12 字数 1005 浏览 5 评论 0 原文

有没有办法做类似于 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 等之外,是否还有一种方法可以实现某种抽象,以便您可以这样做:

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

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

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

我选择 XML 只是作为示例,但我想知道这是否可能,以及它是否涉及太接近 Objective-C 运行时,或者运行时本身是否支持它,以及我将如何实现这样的东西。 这纯粹是为了实验目的,我知道这可能会产生巨大的性能成本。

编辑:
如果可能的话,我想避免使用 Cocoa 等现有框架,并使用基本 Objective-C 对象 Object

Is there a way to do something similar to KVC but use the message name as the key itself? For example, rather than valueForKey:, is there a way for an object to respond to all messages?

For example, say you have an XML document:

<?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>

Besides using the already-available NSXMLDocument and co., would there be a way to implement some sort of abstraction so you could do:

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

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

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

I chose XML just as an example, but I want to know whether this is possible at all, and whether or not it involves getting too close to the Objective-C runtime or whether it is supported by the runtime itself, and how I would go about implementing something like this. This is purely for experimental purposes and I understand that there will likely be significant performance costs.

EDIT:
If possible, I'd like to avoid existing frameworks such as Cocoa and use the base Objective-C object Object.

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

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

发布评论

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

评论(2

祁梦 2024-07-21 05:01:12

您需要实现 forwardInspiration:methodSignatureForSelector: 来处理无法识别的消息。 它是 NSObject 参考中进行了描述

编辑:维基百科有一个 示例 基本上说明了如何为对象完成转发通过实现 forward:performv:

You need to implement forwardInvocation: and methodSignatureForSelector: to handle unrecognized messages. It is described in the NSObject reference.

EDIT: Wikipedia has an example of how forwarding can be accomplished for Object, basically by implementing forward: and performv:.

鹤舞 2024-07-21 05:01:12

感谢 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 抱怨它找不到 asdfasdfasdfasdf 的方法签名>zxcvzxcvzxcvzxcv。 没什么大不了的,它仍然表明这个概念是可行的。 在 Apple 的运行时中,您可以使用 sel_getName(sel) 而不是 get_sel_name(sel)

Thanks to codelogic, I've found out all you need to do for GCC's Objective-C runtime is:

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

The output is:

Received: asdfasdfasdfasdf
Received: zxcvzxcvzxcvzxcv

But of course, GCC complains that it cannot find method signatures for asdfasdfasdfasdf and zxcvzxcvzxcvzxcv. Not a big deal, it still shows that the concept is doable. In Apple's runtime you can use sel_getName(sel) instead of get_sel_name(sel).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文