ios - 避免项目中使用我的 iOS 框架和依赖项之一的重复符号的最佳方法是什么?

标签 ios objective-c static-libraries objective-c-runtime ios-frameworks

这是来自 other post 的引文:

I'm working in a iOS project that includes a static library created by another company. The library include an old version of AFNeworking and I don't have any source files.

Now i need to use a more recent (and less bugged) version of afneworking, but i cannot include the same class twice in the project (of course) because all the "duplicate symbols"

我的问题是我正在准备一个 iOS 框架并且我想避免这种情况在未来。我不是在谈论 AFNetworking,而是其他相当流行的 iOS 框架。 此外,我在原始框架代码中应用了一些自定义更改

我想到的避免“重复符号”和“类 X 在 Y 和 Z 中实现。将使用两者之一”的一种方法是为原始框架类添加一些前缀,但是这是正确的解决方案吗?

更新 1:

我尝试应用 John 的解决方案,但没有成功。我创建了一个简化的项目 ( here is the link to the repo ),其中有两个类 FrameworkClass 仅存在于框架目标中,SharedClass 存在于框架和应用程序目标中,所以也许您可以看看我是否做错了什么。应用程序启动后我仍然得到: objc[96426]:类 SharedClass 在 .../TestFramework.framework/TestFramework 和 .../SymbolsVisibilityTest.app/SymbolsVisibilityTest 中实现。将使用两者之一。哪个是未定义的

更新 2:

这是我根据提供的示例项目的框架输出从 nm 输出的结果:

0000000000007e14 t -[FrameworkClass doFramework]
0000000000007e68 t -[SharedClass doShared]
                 U _NSLog
                 U _NSStringFromSelector
00000000000081f0 s _OBJC_CLASS_$_FrameworkClass
                 U _OBJC_CLASS_$_NSObject
0000000000008240 s _OBJC_CLASS_$_SharedClass
00000000000081c8 s _OBJC_METACLASS_$_FrameworkClass
                 U _OBJC_METACLASS_$_NSObject
0000000000008218 s _OBJC_METACLASS_$_SharedClass
0000000000007fb0 s _TestFrameworkVersionNumber
0000000000007f70 s _TestFrameworkVersionString
                 U ___CFConstantStringClassReference
                 U __objc_empty_cache
                 U _objc_release
                 U _objc_retainAutoreleasedReturnValue
                 U dyld_stub_binder`

更新 3:

我确实通过应用 the solution 设法“隐藏”了 SharedClass 符号由@bleater 和我从 nm 输出现在是:

         U _NSLog
         U _NSStringFromSelector
00001114 S _OBJC_CLASS_$_FrameworkClass
         U _OBJC_CLASS_$_NSObject
00001100 S _OBJC_METACLASS_$_FrameworkClass
         U _OBJC_METACLASS_$_NSObject
         U ___CFConstantStringClassReference
         U __objc_empty_cache
         U _objc_release
         U _objc_retainAutoreleasedReturnValue
         U dyld_stub_binder`

但我仍然在 Xcode 中收到双重实现警告。

最佳答案

您应该限制符号在您正在开发的任何框架或库中的可见性。将默认可见性设置为隐藏,然后将公共(public)界面中的所有功能显式标记为可见。

这避免了您描述的所有问题。然后,您可以包含任何公共(public)库(AFNetworking、SQLite 等)的任何版本,而不必担心将来会发生冲突,因为链接到您的框架或库的任何内容都无法“看到”这些符号。

要将默认可见性设置为隐藏,您可以进入项目设置并将“默认隐藏的符号”设置为"is"。除非您更改它,否则它设置为 NO。

enter image description here

至少有几种方法可以将公共(public)界面中的符号标记为“可见”。一种是使用导出文件,另一种是遍历并将某些函数显式标记为可见:

#define EXPORT __attribute__((visibility("default")))
EXPORT int MyFunction1();

定义显然只是为了方便。您定义一次 EXPORT,然后只需将 EXPORT 添加到所有公共(public)符号。

你可以在这里找到苹果官方文档:

Runtime Environment Programming Guide

更新:

我查看了您的示例项目,看来我给您指出了错误的方向。看来您只能真正隐藏 C 和 C++ 符号。因此,如果您在使用 C 库(如 sqlite)时遇到此问题,则将默认可见性设置为隐藏即可。看起来 Objective C 运行时的性质阻止您真正使符号不可见。您可以标记这些符号的可见性,但对于 Objective-C,这似乎只是一种让链接器强制执行您应该或不应该从库中使用的内容的方法(同时仍然让它们可见)。

因此,如果您在不同的编译单元中使用相同的名称重新定义一个 Objective-C 符号(可能通过在流行的开源库的新版本中进行编译),那么您仍然会发生冲突。

我认为此时您唯一的解决方案是执行您首先建议的操作,并使用唯一标识符为要包含在框架中的符号添加前缀。这不是一个非常优雅的解决方案,但由于 Objective-C 运行时的限制,我相信它可能是可用的最佳解决方案。

关于ios - 避免项目中使用我的 iOS 框架和依赖项之一的重复符号的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27509353/

相关文章:

c++ - 库中所有符号的显式名称修改(也称为名称修饰)

ios - 将带有列表的 map 添加到移动应用程序的表单?

ios - 如何更改 Objective-C 中的 CBAdvertisementDataLocalNameKey 值?

ios - 每次我尝试添加 ZipArchive 或 ssziparchive 时,Xcode 中都会出现很多错误

iOS 使用 UIGraphicsGetImageFromCurrentImageContext 检测屏幕上的某些像素

ios - 在另一个对象中初始化 UISwipeGestureRecognizer 时使用未声明的标识符 'action'

c++ - 我尝试在 Dev-c++ 中使用 usblib,但得到 "undefined reference"?

iphone - Xcode生成的静态库的大小

ios - 扩展和收缩 View 中相邻的 UI 对象

ios - watchKit 控制台日志显示,但 iOS 应用程序不显示?