我有一个需要为不同客户编译的现有应用程序
每个客户端都需要自己的图标和启动画面.
我还希望能够有条件地包括各种功能,具体取决于特定客户端是否需要它们.
我已经尝试为每个客户设置不同的目标,但到目前为止没有太多运气.
具有相同名称的不同资源,但不同的路径不断混淆.
理想情况下,我希望能够通过复制另一个类似的客户端来构建应用程序,然后只需进行最小数量的更改即可为新客户端创建应用程序.
设置此应用程序的最佳方法是什么?
应该是每个客户的单独目标.对于这些功能,我建议首先在目标设置中设置一个标识客户端的宏(在构建选项卡上的"预处理器宏"下),然后使用如下所示的FeatureDefines.h文件:
#ifdef macroClientA // assume client A wants features 1 and 3
# define macroFeature1
# define macroFeature3
#endif
// and similarly for the other clients
Run Code Online (Sandbox Code Playgroud)
现在你可以使用了
#import featureDefines
#ifdef macroFeature1
Run Code Online (Sandbox Code Playgroud)
如果需要特征1,您需要测试的任何地方.
对于单独的图标,您的目标设置可以为每个客户端指定不同的info.plist文件,这些文件可以依次为图标指定不同的文件名.
对于单独的启动屏幕,iOS始终要求启动屏幕命名为Default.png,但它们可以位于项目目录的不同子目录中.您可以通过右键单击Xcode表示"Groups&Files"的位置,选择Target Membership,然后选中要使用的复选框,并确保取消选中其他目标,来控制使用哪个目标.
对于资源,我建议命名您的资源文件,如下所示:
resourceName.ext //如果没有特定于客户端的
resourceName-clientName.ext //客户端特定资源,则使用该通用资源
接下来设置一个通用的资源查找器方法,如下所示:
-(NSString *) resourcePathForResourceName: (NSString *) resourceName extension: (NSString *) ext {
NSString *clientName;
#ifdef macroClientA
clientName = @"clientA";
#endif // and similarly for the other clients
NSString *clientSpecificName = [NSString stringWithFormat: @"%@-%@.%@", resourceName, clientName, ext];
NSString *genericName = [NSString stringWithFormat: @"%@.%@"];
if ([[NSFileManager defaultManager] fileExistsAtPath: clientSpecificName])
return clientSpecificName;
else if ([[NSFileManager defaultManager] fileExistsAtPath: genericName])
return genericName;
else
// handle the error
}
Run Code Online (Sandbox Code Playgroud)
通过该方法运行所有资源文件抓取将允许您在不更改单行代码的情况下将特定于客户端的资源添加到项目中.
我有一个类似的场景,我如何处理它如下:
1)应用程序的核心代码保存在"application_name-base"文件夹中
2)不同的客户端位于其"application_name-client_name"文件夹中
3)项目文件位于客户端文件夹中,包括来自基本文件夹的引用,而不使用副本.
4)客户端项目需要唯一的文件位于客户端文件夹中.通常使用相同名称的图像.或.h .m文件,需要对单个项目是唯一的.还允许您不按项目包含项目中的文件.
保持代码中心,但允许每个客户端使用不同的代码,而不会导致混淆.