Introspect type: id 的参数来决定它是类还是协议
我有以下方法:
-(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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 Objective-C 2 中(即除非您在 OS X 上使用 32 位运行时)
Protocol
被定义为只是一个转发类,请参阅/usr/include/objc/runtime.h.真正的接口没有声明。您可以尝试包含
/usr/inlcude/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.mm
,Protocol
的isa
指针> 对象是在加载可执行文件和库时手动设置,并且从不使用。因此,不要尝试检查
id
是否是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 sayingbut as is written there, no method is publicly supported for an instance of
Protocol
. The only accepted way to deal withProtocol
instances is to use runtime functions, given in Objective-C Runtime Reference. It's not even publicly defined whetherProtocol
is a subclass of anything, and it's not even stated that it implementsNSObject
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 fromObject
(which is a remnant from pre-OpenStep NeXTSTep), not fromNSObject
. So you can't use the familiar methods forNSObject
-derived objects, includingClass
ofNSObject
-derived objects. See the opensourced implementations of Protocol.h and Protocol.m. As you see there, the classProtocol
itself doesn't do anything, because every method just castsself
toprotocol_t
and calls a function. In fact, as can be seen from the function_read_images
and others inobjc-runtime-new.mm
, theisa
pointer of aProtocol
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 aProtocol
or not.If you really need to do this, you can use
But, seriously, don't do it.
这不是由于无法确定它是类还是协议而引起的问题。该错误是由于缺少
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 importProtocol.m
at the top of your implementation file where you're testing argument's type.You can also try using
NSClassFromString()
function which will returnClass
object ornil
. Do note though that ifnil
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 andnil
for undefined protocol.