解决 Objective-C 命名空间冲突的最佳方法是什么? [英] What is the best way to solve an Objective-C namespace collision?

查看:36
本文介绍了解决 Objective-C 命名空间冲突的最佳方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Objective-C has no namespaces; it's much like C, everything is within one global namespace. Common practice is to prefix classes with initials, e.g. if you are working at IBM, you could prefix them with "IBM"; if you work for Microsoft, you could use "MS"; and so on. Sometimes the initials refer to the project, e.g. Adium prefixes classes with "AI" (as there is no company behind it of that you could take the initials). Apple prefixes classes with NS and says this prefix is reserved for Apple only.

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

So far so well. But appending 2 to 4 letters to a class name in front is a very, very limited namespace. E.g. MS or AI could have an entirely different meanings (AI could be Artificial Intelligence for example) and some other developer might decide to use them and create an equally named class. Bang, namespace collision.

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

Okay, if this is a collision between one of your own classes and one of an external framework you are using, you can easily change the naming of your class, no big deal. But what if you use two external frameworks, both frameworks that you don't have the source to and that you can't change? Your application links with both of them and you get name conflicts. How would you go about solving these? What is the best way to work around them in such a way that you can still use both classes?

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

In C you can work around these by not linking directly to the library, instead you load the library at runtime, using dlopen(), then find the symbol you are looking for using dlsym() and assign it to a global symbol (that you can name any way you like) and then access it through this global symbol. E.g. if you have a conflict because some C library has a function named open(), you could define a variable named myOpen and have it point to the open() function of the library, thus when you want to use the system open(), you just use open() and when you want to use the other one, you access it via the myOpen identifier.

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

Is something similar possible in Objective-C and if not, is there any other clever, tricky solution you can use resolve namespace conflicts? Any ideas?

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

Just to clarify this: answers that suggest how to avoid namespace collisions in advance or how to create a better namespace are certainly welcome; however, I will not accept them as the answer since they don't solve my problem. I have two libraries and their class names collide. I can't change them; I don't have the source of either one. The collision is already there and tips on how it could have been avoided in advance won't help anymore. I can forward them to the developers of these frameworks and hope they choose a better namespace in the future, but for the time being I'm searching a solution to work with the frameworks right now within a single application. Any solutions to make this possible?

推荐答案

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

If you do not need to use classes from both frameworks at the same time, and you are targeting platforms which support NSBundle unloading (OS X 10.4 or later, no GNUStep support), and performance really isn't an issue for you, I believe that you could load one framework every time you need to use a class from it, and then unload it and load the other one when you need to use the other framework.

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

My initial idea was to use NSBundle to load one of the frameworks, then copy or rename the classes inside that framework, and then load the other framework. There are two problems with this. First, I couldn't find a function to copy the data pointed to rename or copy a class, and any other classes in that first framework which reference the renamed class would now reference the class from the other framework.

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

You wouldn't need to copy or rename a class if there were a way to copy the data pointed to by an IMP. You could create a new class and then copy over ivars, methods, properties and categories. Much more work, but it is possible. However, you would still have a problem with the other classes in the framework referencing the wrong class.

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

The fundamental difference between the C and Objective-C runtimes is, as I understand it, when libraries are loaded, the functions in those libraries contain pointers to any symbols they reference, whereas in Objective-C, they contain string representations of the names of thsoe symbols. Thus, in your example, you can use dlsym to get the symbol's address in memory and attach it to another symbol. The other code in the library still works because you're not changing the address of the original symbol. Objective-C uses a lookup table to map class names to addresses, and it's a 1-1 mapping, so you can't have two classes with the same name. Thus, to load both classes, one of them must have their name changed. However, when other classes need to access one of the classes with that name, they will ask the lookup table for its address, and the lookup table will never return the address of the renamed class given the original class's name.

这篇关于解决 Objective-C 命名空间冲突的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆