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

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

问题描述

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

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中,它们包含thsoe符号的名称的字符串表示。因此,在您的示例中,您可以使用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天全站免登陆