【问题标题】:Objective-C compiler is leaving out a protocol definitionObjective-C 编译器遗漏了协议定义
【发布时间】:2014-02-07 01:56:09
【问题描述】:

我正在编写几个使用 Objective-C 运行时库的类。这包括在运行时根据其名称检索协议定义。但是,似乎没有被类明确采用或在代码中使用 @protocol(ProtocolName) 引用的协议被排除在编译之外并且在运行时不可用。

例子:

@protocol MyProtocol <NSObject>

-(void)doSomething;

@end

//代码中的其他地方

Protocol *protocol = NSProtocolFromString(@"MyProtocol"); 
// ^ value of "protocol" will be nil when I run the application!

//但是,如果我使用,请执行以下操作:

Protocol *whyDoIHaveToDoThis = @protocol(MyProtocol);
Protocol *protocol = NSProtocolFromString(@"MyProtocol"); 
// ^ value of "protocol" will now be a pointer as expected when I run the application!

有谁知道这是为什么,甚至更好的是,如何强制编译器包含在编译时未使用但我稍后希望在运行时可用的协议定义?

【问题讨论】:

  • 这就是它的工作方式。如果没有类采用该协议,你如何使用它?
  • 这个答案可能会有所帮助:stackoverflow.com/a/11533804/342620
  • 这是意料之中的。编译器不会为协议声明发出元数据,并在使用该协议的任何文件中发出元数据的副本(通过采用它或通过编写 @protocol(ProtoName) 表达式。
  • 感谢所有的 cmets。 @Hot Licks - 可以使用 class_addProtocol() 等函数在运行时分析和采用协议。对于需要在运行时与未知的“外部”代码交互的库、插件和其他类型的代码,即使在编译时没有内部对象采用它们,也可以动态查找协议定义,这一点很重要。我真的很惊讶协议定义被这样剥离,而 Objective-C 是一种动态语言,旨在能够处理未知类型,而这首先是协议的主要用途。
  • 但是协议主要是给编译器的文档,告诉它哪些方法是可用的——它没有真正的运行时函数。 class_copyMethodList 会告诉你运行时有哪些方法。

标签: ios objective-c protocols llvm objective-c-runtime


【解决方案1】:

您可以强制编译器包含该协议,方法是创建一个未调用的使用该协议的虚拟方法。我以前做过:

void preserveProtocolFromBeingTrimmed()
{
     (void)@protocol(BrightnessProtocol);
}

我看到 Apple 在他们的 FxBrightness plug-in from the FxPlug SDK 中使用了这个。

【讨论】:

  • 谢谢!我赞成这个链接到 Apple 示例代码。我希望的答案是强制包含“在编译时未使用”的协议定义,使用上述方法不会出现这种情况。我希望在编译器标志等方面有更多的东西,如果它们不被使用,强制作为编译目标包含的协议标头不会被忽略,但我意识到这样的标志可能不存在并且你的建议可能是最好的/唯一的解决方案。如果没有更好的答案,我会接受你的:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多