小编典典

解决 Objective-C 命名空间冲突的最佳方法是什么?

all

Objective-C 没有命名空间;它很像 C,一切都在一个全局命名空间中。通常的做法是在类前面加上首字母,例如,如果你在 IBM
工作,你可以在它们前面加上“IBM”;如果你为微软工作,你可以使用“MS”;等等。有时缩写是指项目,例如 Adium
为类加上“AI”前缀(因为它背后没有公司,你可以使用缩写)。Apple 用 NS 为类添加前缀,并表示此前缀仅供 Apple 使用。

到目前为止一切顺利。但是在前面的类名后面附加 2 到 4 个字母是一个非常非常有限的命名空间。例如,MS 或 AI 可能具有完全不同的含义(例如 AI
可能是人工智能),其他一些开发人员可能决定使用它们并创建一个同名的类。 Bang ,命名空间冲突。

好的,如果这是您自己的一个类和您正在使用的外部框架之一之间的冲突,您可以轻松更改类的命名,没什么大不了的。
但是,如果您使用两个外部框架,这两个框架您都没有源代码并且无法更改,该怎么办?
您的应用程序与它们都链接,并且您会遇到名称冲突。你将如何解决这些问题?以您仍然可以使用这两个类的方式解决它们的最佳方法是什么?

在 C 中,您可以通过不直接链接到库来解决这些问题,而是在运行时使用 dlopen() 加载库,然后使用 dlsym()
找到您要查找的符号并将其分配给全局符号(您可以以任何你喜欢的方式命名),然后通过这个全局符号访问它。例如,如果您因为某个 C 库有一个名为 open()
的函数而发生冲突,您可以定义一个名为 myOpen 的变量并让它指向该库的 open() 函数,因此当您想使用系统 open() ,您只需使用 open()
,当您想使用另一个时,您可以通过 myOpen 标识符访问它。

在 Objective-C 中是否有类似的可能,如果没有,是否有任何其他聪明、棘手的解决方案可以用来解决命名空间冲突?有任何想法吗?


更新:

只是为了澄清这一点:当然欢迎建议如何提前避免命名空间冲突或如何创建更好的命名空间的答案;但是,我不会接受它们作为 答案
,因为它们不能解决我的问题。我有两个库,它们的类名发生冲突。我无法改变它们;我没有任何一个的来源。碰撞已经存在,关于如何提前避免碰撞的提示将不再有帮助。我可以将它们转发给这些框架的开发人员,并希望他们将来选择更好的命名空间,但目前我正在寻找一种解决方案,以便现在在单个应用程序中使用这些框架。有什么解决方案可以使这成为可能吗?


阅读 64

收藏
2022-08-19

共1个答案

小编典典

如果您不需要同时使用两个框架中的类,并且您的目标是支持 NSBundle 卸载的平台(OS X 10.4 或更高版本,不支持
GNUStep),那么性能对您来说真的不是问题,我相信您可以在每次需要使用其中的一个类时加载一个框架,然后在需要使用另一个框架时卸载它并加载另一个框架。

我最初的想法是使用 NSBundle
加载其中一个框架,然后复制或重命名该框架内的类,然后加载另一个框架。这有两个问题。首先,我找不到复制指向重命名或复制类的数据的函数,并且第一个框架中引用重命名类的任何其他类现在将引用来自其他框架的类。

如果有办法复制 IMP 指向的数据,则不需要复制或重命名类。您可以创建一个新类,然后复制
ivars、方法、属性和类别。更多的工作,但这是可能的。但是,您仍然会遇到框架中引用错误类的其他类的问题。

编辑:据我所知,C 和 Objective-C 运行时之间的根本区别是,当库被加载时,这些库中的函数包含指向它们引用的任何符号的指针,而在
Objective-C 中,它们包含这些符号的名称。因此,在您的示例中,您可以使用 dlsym
获取符号在内存中的地址并将其附加到另一个符号。库中的其他代码仍然有效,因为您没有更改原始符号的地址。Objective-C
使用查找表将类名映射到地址,并且是 1-1
映射,因此不能有两个具有相同名称的类。因此,要加载这两个类,其中一个必须更改其名称。但是,当其他类需要访问具有该名称的类之一时,

2022-08-19