我有以下方法:
-(void)SomeMethod:(id)classOrProtocol;
它会像这样调用:
[self someMethod:@protocol(SomeProtocol)];
或者
[self someMethod:[SomeClass class]];
在方法体中,我需要决定是否| classOrProtocol |是:
任何类别(类别)或任何协议(协议)或其他任何内容
[[classOrProtocol class] isKindOfClass: [Protocol class]]
导致(构建)错误:
接收方'协议'是一个前向类,相应的@interface可能不存在
那么如何从一个类中告诉一个协议呢?
答案 0 :(得分:2)
在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 Runtime Reference中给出的运行时函数。它甚至没有公开定义Protocol
是否是任何事物的子类,甚至没有声明它实现NSObject
协议。所以你不能在它上面调用任何方法。
当然,您可以使用运行时的源代码来查看正在发生的事情。 Protocol
继承自Object
(来自OpenStep之前的NeXTSTep的残余),而非NSObject
。因此,您无法使用熟悉的NSObject
派生对象方法,包括Class
个NSObject
派生对象。请参阅Protocol.h和Protocol.m的开源实现。正如您所看到的,类Protocol
本身不会执行任何操作,因为每个方法只会将self
强制转换为protocol_t
并调用函数。实际上,从函数_read_images
和objc-runtime-new.mm
中的其他函数可以看出,isa
对象的Protocol
指针是手动设置 加载可执行文件和库时,从未使用过。
因此,请勿尝试检查id
是否为Protocol
。
如果您确实需要这样做,可以使用
id foo=...;
if(foo->isa==class_getClass("Protocol")){
...
}
但是,严肃地说,不要这样做。
答案 1 :(得分:-1)
这不是由于无法确定它的类或协议而导致的问题。该错误是由Protocol
类的缺少接口引起的。确保在实验文件的顶部导入Protocol.m
,您正在测试参数的类型。
您还可以尝试使用NSClassFromString()
函数,该函数将返回Class
个对象或nil
。请注意,如果返回nil
,则并不意味着参数是协议。它只是意味着它也可能是未定义的类!
还有方法NSProtocolFromString
返回适当的结果 - 协议协议和未定义协议的nil
。