Objective-C运行时:检查类是否符合协议的最佳方法?

175
我有一个类(但没有实例),需要知道它是否符合特定的协议。但是,该类可以被多次子类化,并且class_conformsToProtocol()会忽略在超类上声明的协议。
我可以使用class_getSuperclass()并递归检查层级中所有向上的类,直到超类为nil。然而,我想知道是否对于深度嵌套的类层次结构来说这种方法可能效率低下,或者是否有更好的方式?
换句话说,在Objective-C运行时方法中如何最好地实现NSObject方法conformsToProtocol以便它可以发现超类上的协议?
 [myObject conformsToProtocol:@protocol(MyProtocol)];

如果我在递归地沿着类层次结构向上走的路上正确,就让我知道。

3个回答

312

根据文档

[MyClass conformsToProtocol:@protocol(MyProtocol)];

应该可以工作。


4
没错,当时很晚了,而且 Xcode 没有给出代码补全建议。我查看了 Class 的定义,发现它是 "typedef struct objc_class *Class",所以我没有查看 NSObject 类的参考文档。 - CodeSmile
有没有办法在实例上完成,而不是在类上完成?我的self.delegate 实现了多个协议,我想检查它是否符合其他协议,而不仅仅是它的类。 - Konrad Piascik
@KonradPiascik 只需在实例上调用它:[someObject conformsToProtocol:@protocol(MyProtocol)] - Wevah

4

或者,如果它是一个普通指针,比如:

Class<MyProtocol> someClassPointer = nil;

您可以使用:

[someClassPointer.class conformsToProtocol:@protocol(MyProtocol)];

0

检查类是否符合协议?

两种方法

使用conformsToProtocol

  • 语法
    • [someClassObj conformsToProtocol: objc_getProtocol("YourProtocolName")]
  • 示例
(lldb) po self
<AKAnisetteProvisioningService: 0x105f16870>

(lldb) po Protocol * $akaisdProto = objc_getProtocol("AKAppleIDSigningDaemonProtocol")
(lldb) po $akaisdProto
<Protocol: 0x1dc7d2e90>

(lldb) po [self conformsToProtocol: $akaisdProto]
0x0000000000000001

使用 class_conformsToProtocol

  • 语法
    • class_conformsToProtocol(NSClassFromString(@"YourClassName"), objc_getProtocol("YourProtocolName"))
  • 示例
(lldb) po Class $akapsClass = NSClassFromString(@"AKAnisetteProvisioningService")
(lldb) po $akapsClass
AKAnisetteProvisioningService

(lldb) po Protocol * $akaisdProto = objc_getProtocol("AKAppleIDSigningDaemonProtocol")
(lldb) po $akaisdProto
<Protocol: 0x1dc7d2e90>

(lldb) po class_conformsToProtocol($akapsClass, $akaisdProto)
0x0000000000000001

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接