问题描述
我有一个包含2个目标的XCode项目(两个iPhone应用程序共享相同代码的95%)。
但是,一个模块不是可共享的;我的解决方案(不起作用)是将2个子目录添加到我的 Classes /
我的项目目录中的文件夹 - 每个目标一个。在每个目录中,我放置了一个视图控制器类,名为 ExampleSentencesViewController
。当然,每个文件都只是其中一个目标的一部分 - 我正在寻找一个自动切换,根据目标使用哪个实现。
在每个目标的设置中,我将每个目录添加到Header Search Paths设置中(每个目标的每个路径)。
奇怪的是,它只编译原始目标。我后来添加的目标不会编译,声称我已经包含相同的头两次(有两个文件,公平)。如何让XCode忘记原始标题?
我尝试删除我的项目中的.h文件,但这似乎没有帮助。
任何帮助都是值得赞赏的。 完全限定标题路径在单独的实现文件中,根据您定义的一个搜索目录:
#include< MONProject / Source / ExampleSentencesViewController.h> code>
vs
#include< MONSecondProject / Source / ExampleSentencesViewController.h>
根据说明进行更新:
理想情况下,您需要为共享代码创建一个静态库。
对于一个简单的情况...您可以 通过在项目根目录中填充名为 ExampleSentencesViewController.h
的标头,然后像下面这样填充它:
/ *您必须defi (目标级别为MON_BUILD_MON_FIRST_PROJECT或MON_BUILD_MON_SECOND_PROJECT)* /
#if(已定义(MON_BUILD_MON_FIRST_PROJECT)&& (MON_BUILD_MON_SECOND_PROJECT))
#error无效配置:无法指定要编译的两个项目
#elif defined(MON_BUILD_MON_FIRST_PROJECT)
/ *一些完全限定的路径:* /
#包括< MONFirstProject / ExampleSentencesViewController.h>
#elif defined(MON_BUILD_MON_SECOND_PROJECT)
/ *其他完全限定路径:* /
#include
#else
#error呃......你想要建立哪个项目?
#endif
或者您可以使用这些定义来有条件地启用/禁用界面和实现具有重复名称的类(然后将它们都包含在项目的声明中:
/ * MONFirstProject / ExampleSentencesViewController。 h> * /
#if defined(MON_BUILD_MON_FIRST_PROJECT)
@interface ExampleSentencesViewController:NSViewController
/ * ... * /
@end
#endif
...但这需要在您的发行版中包含这两个标头(如果适用)。
包含的一些更精细的细节可能会因您声明搜索路径的方式而有所不同(例如,它们是递归的还是不是?),以及您是否使用副本头构建阶段xcodeproj。如果您在include指令,发现选项,预处理器声明(条件)中过于宽松,那么维护共享代码的两个项目可能会变得混乱al编译/可见性)和/或构建配置,所以...这就是为什么我建议共享位的库。这个有条件的东西(在前面的两个例子中)容易出错,并且不能很好地发展或扩展。这样做也是混淆开发工具包中其他工具的好方法。实际上,我比预处理器更喜欢它(假设您可以分发两个类):
$ b $
- (UIViewController *)newViewControllerForMyAwesomeView {
if(IsAppMONFirstProject){
return [[MONFirstProjectViewController alloc] init ...];
else if(IsAppMONSecondProject){
return [[MONSecondProjectViewController alloc] init ...];
}
else {
assert(0&&肯定会破坏你的代码,现在它被3个或更多的项目引用了。
返回0;
$ / code $ / pre
如果你只是维护相同的两个版本标题,那么实践将会有很大的不同。
无论如何...这个应该足够的想法来解决你的问题 - 你只需要确定更小的邪恶。
I have an XCode project with 2 targets (both are iPhone apps sharing 95% of the same code).
However, one module isn't "shareable"; the implementations are too different.
My solution (that is not working) was to add 2 subdirectories to my Classes/
folder in my project directory - one for each target. In each directory, I've placed a view controller class, called ExampleSentencesViewController
. Of course, each file is compiled as part of only one of the targets - I'm looking for an "automatic switching" of which implementation to use based on the target.
Inside each target's settings, I added each directory to the "Header Search Paths" setting (each path for each target).
Oddly, it only compiles for the original target. The target I added later won't compile, claiming that I've included the same header twice (there ARE two files, to be fair). How do I get XCode to forget about the original header??
I've tried deleting the .h files out of my project, but that does not seem to help.
Any help is appreciated.
解决方案 fully qualify the header paths in the separate implementation files, based on one of your defined search directories:
#include <MONProject/Source/ExampleSentencesViewController.h>
vs
#include <MONSecondProject/Source/ExampleSentencesViewController.h>
update based on clarification:
ideally, you'd create a static library for the shared code.
for a simple case... you could take the direct approach by populating a header in your project's root, named ExampleSentencesViewController.h
, and populating it like so:
/* 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
or you could just use these defines to conditionally enable/disable the interface and implementation of the classes with duplicate names (and then just include them both in the project's declaration of:
/* MONFirstProject/ExampleSentencesViewController.h> */
#if defined(MON_BUILD_MON_FIRST_PROJECT)
@interface ExampleSentencesViewController : NSViewController
/* ... */
@end
#endif
…but this will require to include both headers in your distribution (if applicable).
some of the finer details of inclusion can vary based on how you've declared your search paths (e.g., are they recursive or not?) and whether you use copy headers build phases in your xcodeproj. maintaining both projects which share code can become messy if you've been too relaxed in your include directives, discovery options, preprocessor declarations (conditional compilation/visibility) and/or build configurations so... that's why i recommend a library for the shared bits. this conditional stuff (in the two previous examples) is error prone and doesn't evolve or scale well. doing this is also a good way to confuse other tools in the development toolkit.
in fact, i prefer this over the preprocessor (assuming you're able to distribute both classes):
- (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;
}
}
if you're merely maintaining two versions of the same title, then practices will be much different.
anyways... this should be enough ideas to solve your problem - you just have to determine the lesser evil.
这篇关于XCode如何处理多个目标中的#import标题语句?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!