【问题标题】:Is there any introspection method to get all adopted protocols for a class in Objective-C?是否有任何自省方法来获取 Objective-C 中一个类的所有采用的协议?
【发布时间】:2013-06-08 21:21:07
【问题描述】:

有一个-[NSObject conformsToProtocol:] 方法可以检查是否采用了特定协议。有没有什么方法可以获取一个类的所有采用的协议,而不是检查一个列表?

【问题讨论】:

  • 你到底想用这个完成什么?
  • @RichardJ.RossIII 我经常使用协议一致性,我需要一些通用对象才能选择并将工作分派到适当的目标(例如,通用UITableViewDataSource 能够为给定对象选择适当的单元格,然后设置该对象);我认为它更易于维护,并且调度程序需要更少的重新声明来通过运行时找到合适的目标,然后查询它们的期望。对这种模式有什么想法吗?

标签: objective-c introspection objective-c-runtime objective-c-protocol


【解决方案1】:

有一个更优雅的解决方案:class_copyProtocolList()直接返回一个类采用的协议。用法:

Class cls = [self class]; // or [NSArray class], etc.
unsigned count;
Protocol **pl = class_copyProtocolList(cls, &count);

for (unsigned i = 0; i < count; i++) {
    NSLog(@"Class %@ implements protocol <%s>", cls, protocol_getName(pl[i]));
}

free(pl);

【讨论】:

  • 人们只应该记住,这个列表不包含超类采用的协议,所以 - 根据这个列表的用途 - 可能有必要沿着超类链走并调用class_copyProtocolList() 再次。
  • @MartinR 确切地说,我实际上很难弄清楚为什么它没有列出NSMutableDictionary 的协议...
  • 这是一个很好的答案。它工作得很好。它可能不适用于 ARC。但它肯定会与非ARC一起使用。谢谢。
  • 如果您尝试让它与 ARC 一起工作并遇到编译错误,只需在 Protocol **pl 之前添加 __unsafe_unretained
【解决方案2】:

正好有NSObject +conformsToProtocol;协议一致性被声明为@interface 的一部分,因此它并不特定于每个实例。所以例如

if( [[self class] conformsToProtocol:@protocol(UIScrollViewDelegate)])
    NSLog(@"I claim to conform to UIScrollViewDelegate");

根本不需要深入到 C 级运行时方法,至少对于您问题的第一部分。 NSObject 中没有任何内容可用于获取支持的协议列表。

【讨论】:

    【解决方案3】:

    你可以试试objc_copyProtocolList

    即你得到所有协议的列表,然后通过迭代列表检查当前对象是否符合特定协议。

    编辑:

    H2CO3 溶液确实更好

    【讨论】:

    • class_copyProtocolList()
    • 如何实际使用?
    • 我不认为objc_copyProtocolList() 在这里是正确的选择——它可以在任何地方获取所有存在的协议。 class_copyProtocolList() 告诉你一个类实际声明符合哪些协议。
    猜你喜欢
    • 1970-01-01
    • 2016-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多