X类在Y和Z中实现。将使用其中一个

时间:2012-01-16 21:11:52

标签: objective-c

我有一个Objective-c“工具”(控制台)程序,可以在运行时动态加载objective-c bundle。一些bundle文件共享来自同一框架的类,所以我得到了“将两个实现的类”消息转储到控制台。

它不会阻止任何工作,但在控制台上显示消息有点烦人。有没有办法防止它们被丢弃?是否有一种方法可以更改捆绑包,因此它们不会编译/链接相同的类?

4 个答案:

答案 0 :(得分:3)

我以前一直在这艘船上,并不是一艘好船。我花了很长时间投资最好的方法来避免运行时类名称冲突。解决方案是:

  1. 创建一个预构建脚本,用于解析头文件中的所有@interface声明,并获取所有类名。此脚本生成一个新标头,其中包含以下内容:

    #define MyClass        MyClass_Target
    #define MyOtherClass   MyOtherClass_Target
    #define MyThirdClass   MyThirdClass_Target
    

    (显然,_Target后缀是由您的预构建脚本能够查看和使用的构建参数设置的。

    该脚本可以是Perl或Python脚本,只扫描*.h之后提取单词的每个@interface文件。

  2. 将构建配置为自动包含生成的头文件,这样您就不必在每个源文件中手动包含生成的头。

  3. 如果您的捆绑包有笔尖,它会增加额外的复杂性,但仍然可以完成。创建另一个替换现有“Nib编译器”的脚本。这个程序基本上执行相同的类重命名,但对于nib(它很容易,因为nib文件是XML)。我不记得在哪里设置它,但在Xcode中有一个位置允许您选择如何“编译”Nib文件。您的nib编译器脚本基本上是一个包装器,它重命名nib中的类,然后调用真正的nib编译器(您可以通过查看构建日志来了解它是如何调用的)。

  4. 有效吗?

    是的,即使在调试情况下,它的效果也非常好。当您点击断点时,Xcode会显示类的名称及其目标后缀,因此您知道自己所在的捆绑包,尽管源代码显示的内容不同。 “修复&继续“尽我所能地工作。

    另外,因为类重命名是在编译时之前完成的,所以它不会影响源代码版本控制,与Interface Builder的交互等等。

    问题

    • 动态生成的类名不起作用,例如从Class返回的NSClassFromString个对象,除非代码知道必要的后缀。

    • 这种复杂的设置需要一些维护。一旦我完成并运行它就能很好地满足我们的需求,但是它时不时需要进行调整才能保证它的顺利运行。

答案 1 :(得分:3)

  • 如果它们是不同的实现,请使用唯一的前缀。

  • 如果它们是相同的实现并且只是由多个图像导出,请重新配置目标,使其仅导出一个。

具体做法是:

  

是否有一种方法可以更改捆绑包,因此它们不会编译/链接相同的类?

将这些共享类放在一个单独的框架中,不要将它们作为bundle的一部分进行编译 - 只需将bundle链接到共享的框架即可。

答案 2 :(得分:0)

您是否尝试过仅将共享类的标头(@interface s)添加到软件包中(以便编译器知道API),而不是代码文件(@implementation s)?

由于您要链接一个包,链接器(ld)不应该抱怨它找不到给定类的实现 - 它会将此任务委托给动态链接器( dyld)一旦你在主程序中加载了bundle就会启动它。然后dyld应该自动在bundle和program之间建立必需的引用。

答案 3 :(得分:0)

如果您是插件包的开发者,您可以将-undefined dynamic_lookup作为其他链接器标志传递,并从插件中删除所有库中的所有库(在主二进制文件和插件中)