XCode如何处理多个目标中的#import头语句?

时间:2010-11-06 08:43:26

标签: iphone xcode ios import header

我有一个包含2个目标的XCode项目(两个iPhone应用程序共享95%的相同代码)。 但是,一个模块不是“可共享的”;实施方式太不同了。

我的解决方案(不起作用)是将2个子目录添加到项目目录中的Classes/文件夹中 - 每个目标一个。在每个目录中,我放置了一个名为ExampleSentencesViewController的视图控制器类。当然,每个文件都只编译为一个目标的一部分 - 我正在寻找一个“自动切换”,根据目标使用哪个实现。

在每个目标的设置中,我将每个目录添加到“标题搜索路径”设置(每个目标的每个路径)。

奇怪的是,它只针对原始目标进行编译。我后来添加的目标将无法编译,声称我已经包含了两次相同的标题(有两个文件,公平)。如何让XCode忘记原始标题?

我尝试从我的项目中删除.h文件,但这似乎没有帮助。

感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

根据您定义的一个搜索目录完全限定单独实现文件中的标头路径:

#include <MONProject/Source/ExampleSentencesViewController.h>

VS

#include <MONSecondProject/Source/ExampleSentencesViewController.h>

根据说明进行更新:

理想情况下,您需要为共享代码创建一个静态库。

对于一个简单的案例......你可以采用直接的方法,在你的项目的根目录中填充一个名为ExampleSentencesViewController.h的标题,然后像这样填充它:

/* you must define either MON_BUILD_MON_FIRST_PROJECT or MON_BUILD_MON_SECOND_PROJECT at the target level */

#if (defined(MON_BUILD_MON_FIRST_PROJECT) && defined(MON_BUILD_MON_SECOND_PROJECT))
#error invalid configuration: you cannot specify both projects to be compiled
#elif defined(MON_BUILD_MON_FIRST_PROJECT)
/* some fully qualified path: */
#include <MONFirstProject/ExampleSentencesViewController.h>
#elif defined(MON_BUILD_MON_SECOND_PROJECT)
/* some other fully qualified path: */
#include <MONSecondProject/ExampleSentencesViewController.h>
#else
#error uh... which project are you trying to build?
#endif

或者您可以使用这些定义来有条件地启用/禁用具有重复名称的类的接口和实现(然后将它们包含在项目的声明中:

/* MONFirstProject/ExampleSentencesViewController.h> */

#if defined(MON_BUILD_MON_FIRST_PROJECT)
@interface ExampleSentencesViewController : NSViewController
/* ... */
@end
#endif

...但是这需要在您的发行版中包含两个标题(如果适用)。

包含的一些更精细的细节可能会根据您声明搜索路径的方式(例如,它们是否递归?)以及您是否在xcodeproj中使用复制标头构建阶段而有所不同。如果您在include指令,发现选项,预处理器声明(条件编译/可见性)和/或构建配置方面过于宽松,那么维护共享代码的两个项目都会变得混乱...这就是为什么我推荐共享库的原因位。这个有条件的东西(在前两个例子中)容易出错,并且不会发展或扩展。这样做也是混淆开发工具包中其他工具的好方法。

事实上,我更喜欢这个而不是预处理器(假设你能够分发这两个类):

- (UIViewController *)newViewControllerForMyAwesomeView {
    if (IsAppMONFirstProject) {
        return [[MONFirstProjectViewController alloc] init...];
    }
    else if (IsAppMONSecondProject) {
        return [[MONSecondProjectViewController alloc] init...];
    }
    else {
        assert(0 && "definitely break up your code, now that it is referenced by 3 or more projects");
        return 0;
    }
}

如果您只是维护同一标题的两个版本,那么实践会有很大不同。

无论如何......这个应该足够的想法来解决你的问题 - 你只需要确定较小的邪恶。