Introspect type: id 的参数来决定它是类还是协议

发布于 2024-12-06 01:21:11 字数 521 浏览 0 评论 0原文

我有以下方法:

-(void)SomeMethod:(id)classOrProtocol;

它将像这样调用:

[self someMethod:@protocol(SomeProtocol)];

或者

[self someMethod:[SomeClass class]];

在方法体内我需要决定是否 |classOrProtocol|是:

任何类(Class)或任何协议(Protocol)或任何其他

[[classOrProtocol class] isKindOfClass: [Protocol class]]

结果都会导致(构建)错误:

接收者“协议”是一个转发类,对应的@interface可能不存在

那么我如何区分协议、类和其他类呢?

I have the following method:

-(void)SomeMethod:(id)classOrProtocol;

It will be called like this:

[self someMethod:@protocol(SomeProtocol)];

Or

[self someMethod:[SomeClass class]];

Within the method body I need to decide if |classOrProtocol| is:

Any Class(Class) OR Any Protocol(Protocol) OR Anything else

[[classOrProtocol class] isKindOfClass: [Protocol class]]

Results in a (build)error:

Receiver 'Protocol' is a forward class and corresponding @interface may not exist

So how can I tell a Protocol from a Class from anything else?

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

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

发布评论

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

评论(2

千紇 2024-12-13 01:21:11

在 Objective-C 2 中(即除非您在 OS X 上使用 32 位运行时)Protocol 被定义为只是一个转发类,请参阅/usr/include/objc/runtime.h.真正的接口没有声明。您可以尝试包含 /usr/inlcude/objc/Protocol.h

#import <objc/Protocol.h>

但正如其中所写,Protocol 实例没有公开支持任何方法。处理 Protocol 实例的唯一可接受的方法是使用运行时函数,在 Objective-C 运行时参考。甚至没有公开定义 Protocol 是否是任何东西的子类,甚至没有声明它实现 NSObject 协议。所以你不能调用它的任何方法。

当然你可以使用运行时的源代码来看看发生了什么。 Protocol 继承自 Object(这是 OpenStep NeXTSTep 之前的残余),而不是继承自 NSObject。因此,您不能对 NSObject 派生对象使用熟悉的方法,包括 NSObject 派生对象的 Class 。请参阅 Protocol.h 的开源实现以及协议.m。正如您所看到的,类 Protocol 本身不执行任何操作,因为每个方法只是将 self 转换为 protocol_t 并调用函数。事实上,从 objc-runtime-new.mmProtocolisa 指针> 对象是在加载可执行文件和库时手动设置,并且从不使用。

因此,不要尝试检查 id 是否是 Protocol

如果你确实需要这样做,你可以使用

id foo=...;
if(foo->isa==class_getClass("Protocol")){
    ...
}

但是,说真的,不要这样做。

In Objective-C 2 (i.e. unless you use 32 bit runtime on OS X) Protocol is defined to be just a forward class, see /usr/include/objc/runtime.h. The real interface is nowhere declared. You can try to include /usr/inlcude/objc/Protocol.h by saying

#import <objc/Protocol.h>

but as is written there, no method is publicly supported for an instance of Protocol. The only accepted way to deal with Protocol instances is to use runtime functions, given in Objective-C Runtime Reference. It's not even publicly defined whether Protocol is a subclass of anything, and it's not even stated that it implements NSObject protocol. So you can't call any method on it.

Of course you can use the source code of the runtime to see what's going on. Protocol inherits from Object (which is a remnant from pre-OpenStep NeXTSTep), not from NSObject. So you can't use the familiar methods for NSObject-derived objects, including Class of NSObject-derived objects. See the opensourced implementations of Protocol.h and Protocol.m. As you see there, the class Protocol itself doesn't do anything, because every method just casts self to protocol_t and calls a function. In fact, as can be seen from the function _read_images and others in objc-runtime-new.mm, the isa pointer of a Protocol object is set by hand when the executable and libraries are loaded, and never used.

So, don't try to inspect whether an id is a Protocol or not.

If you really need to do this, you can use

id foo=...;
if(foo->isa==class_getClass("Protocol")){
    ...
}

But, seriously, don't do it.

染火枫林 2024-12-13 01:21:11

这不是由于无法确定它是类还是协议而引起的问题。该错误是由于缺少 Protocol 类的接口引起的。确保在测试参数类型的实现文件顶部导入 Protocol.m

您还可以尝试使用 NSClassFromString() 函数,该函数将返回 Class 对象或 nil。但请注意,如果返回 nil 并不意味着该参数是协议。这只是意味着它也可能是未定义的类!

还有一个方法 NSProtocolFromString 返回适当的结果 - Protocol 表示协议,nil 表示未定义的协议。

This is not an issue 'caused by inability to determine whether it's class or protocol. The error is 'caused by missing interface of Protocol class. Make sure you import Protocol.m at the top of your implementation file where you're testing argument's type.

You can also try using NSClassFromString() function which will return Class object or nil. Do note though that if nil is returned it doesn't mean that argument is protocol. It just means that it could be undefined class too!

There is also method NSProtocolFromString which returns appropriate results - Protocol for protocol and nil for undefined protocol.

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