为不同客户定制iPhone应用程序

13

我有一个已经存在的应用程序,需要为不同的客户编译。

每个客户都需要自己的图标和启动画面。
我还希望能够有条件地包含各种功能,具体取决于特定客户是否需要。

我尝试为每个客户设置不同的目标,但到目前为止没有太大成功。
相同名称但具有不同路径的不同资源会混淆在一起。

理想情况下,我希望能够通过复制一个类似的客户端来构建一个应用程序,然后只需进行最少量的更改即可为新客户创建应用程序。

如何最佳地设置此应用程序?


感谢您为此问题设置赏金。我也遇到了同样的问题。顺便提一下,可以看看我在类似主题上的问题:http://stackoverflow.com/questions/4112483/how-does-xcode-handle-import-header-statements-in-with-multiple-targets - makdad
7个回答

10

为每个客户端设置单独的目标应该是正确的方式。对于特性,建议首先在目标设置中设置一个宏来识别客户端(在构建选项卡下的“预处理器宏”中),然后创建一个名为FeatureDefines.h的文件,其内容如下:

#ifdef macroClientA // assume client A wants features 1 and 3
#  define macroFeature1
#  define macroFeature3
#endif

// and similarly for the other clients

现在你可以使用

#import featureDefines
#ifdef macroFeature1

任何需要测试功能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
}

通过该方法运行您所有的资源文件获取,将允许您向项目添加特定于客户端的资源,而无需更改任何代码。


谢谢,我接受这个答案,因为它更或多或少是我想要解决问题的方式。 - John La Rooy

7
我有一个类似的情况,我的处理方式如下:
1)应用程序的核心代码存放在“应用程序名称-base”文件夹中。
2)不同的客户端存放在它们各自的“应用程序名称-客户端名称”文件夹中。
3)项目文件位于客户端文件夹中,并包含来自基础文件夹的引用,而不使用复制。
4)需要针对客户端项目唯一的文件位于客户端文件夹中。通常是使用相同名称的图像或.h .m文件,这些文件需要针对个别项目进行唯一设置。这也允许您按项目选择不包括文件。
这样可以保持代码集中,同时又可以为不同的客户端提供不同的代码,而不会导致混淆。

这个可以使用不同的目标来指定要使用哪个源文件夹,比名称混淆更加清晰。 - Nuthatch

3
您可以为每个客户端创建一个单独的目标,并将每个客户的资产放在以其名称命名的文件夹中。我曾经做过类似的事情,有两个项目有很多共同点,只需要从每个项目中添加/删除相应的资产。
对于您的情况,此时您只需为每个目标添加新的具体客户资源文件夹,而不需要进行任何代码更改。如果路径是一个问题,您可以考虑使用 [UIImage imageNamed:] 方法,它不需要全路径,只需要文件名即可。

1

谢谢,我会研究自动化脚本。 - John La Rooy

0

编写代码以允许外部配置文件完成大部分设置,然后在目标中包含正确的资源。使用一个项目为每个客户端创建一个新目标,您可以选择将哪些资源包含在每个目标中。如果您在处理多个目标时遇到问题,可以使用git来管理核心项目,然后为每个客户端创建一个分支。


0

我会为客户创建一个设置界面,让他们能够根据自己公司/个人的需求来自定义应用程序。例如,从他们的照片库提供图片等。


0

您可以为每个客户创建一个项目,并将所有源文件包含在同一路径中,而无需将它们复制到项目目录中。 因此,在使用相同的代码库的同时,您将能够替换项目中的图标/启动画面。 这似乎是迄今为止最简单的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接