如何使用不同的皮肤/品牌构建不同版本的应用程序?

时间:2012-07-31 22:45:20

标签: ios xcode

我正在创建一个通用应用程序,它将为不同的客户提供不同的构建。该应用程序对于每个客户是99.5%相同,每个客户的差异都标有客户自己的特定图像和文本和应用程序图标等。

显然,这可以使用以下标志来完成:

#if defined (CUSTOMER_A)
    NSString* text = @"Text for customer A";
    UIImage *image = [UIImage imageNamed:@"customerAImage"];
#elseif defined (CUSTOMER_B)
    NSString* text = @"Text for customer B";
    UIImage *image = [UIImage imageNamed:@"customerBImage"];

但显然我想避免这种情况,只是:

   NSString* text = @"Text";
   UIImage *image = [UIImage imageNamed:@"image"];

(文本可以本地化,因此它将在最终版本中使用NSLocalizedString。)

我想知道一种可能的方法是将项目放入工作空间以及一些静态库,每个静态库包含每个客户的特定文本和图像,然后使用不同的方案来创建不同的构建。因此,方案A将创建一个使用主项目和静态库A构建的目标。

我从一个小概念证明开始,但在对它进行过多研究之前,我首先要检查这是一种可行且合理的方法,或者是否有更好的选择。如果可行,那么我会想到几个问题:

  • 如何从主项目中的代码访问静态库中的图像?是否必须创建一个包来访问库的内容,这是如何完成的?

  • 是否可以根据使用的方案更改应用程序桌面和市场图标?

  • 是否可以为每个方案指定一组不同的分发证书等?

  • 静态库是否真的不能包含本地化变体?

这适用于iOS,因此无法使用此框架。

感谢您的反馈。

(P.S。构建系统将使用Jenkins自动化)。

5 个答案:

答案 0 :(得分:8)

您只需在项目中创建多个目标即可 每个目标(客户/品牌)的资源文件夹。 以下是如何实现这一目标:

  1. 创建两个新的资源文件夹 一个。 Resources_Customer1 湾Resource_Customer2
  2. 将相应的资源复制到相应的文件夹
  3. 选择项目 - >目标
  4. 复制目标
  5. 自定义[复制构建资源]中的资源名称,使其指向适当的
    客户/品牌
  6. 根据所选目标测试并验证相应的目标运行。
  7. 希望这有帮助!

答案 1 :(得分:5)

您计划支持多少种变体?如果您拥有超过一小部分,那么拥有目标/项目/等会变得笨拙。这大致就是我们所做的:

  • Jenkins监视源代码控制并构建它看到的任何新提交。
  • Jenkins将输出.app与一系列“皮肤”
  • 归档
  • 家庭酿造的网站挂钩Jenkins API并列出(分支,皮肤)的所有排列。
  • “用户”选择(分支,皮肤),自制网站调用一个脚本,将皮肤“应用”到.app包,签名并将其打包成.ipa然后安装到用户的设备。

皮肤“应用程序”过程基本上包括提供“皮肤”目录列表,这些目录是要复制到应用程序包中的文件。皮肤会覆盖任何重复的文件。应用程序的基础Info.plist与skin目录中指定的任何更改合并。

基本上,我们尝试尽可能地从代码本身中分离出外观。我们发现任何涉及Xcode本身的解决方案都涉及从开发人员的头皮中手动自行去除头发。

答案 2 :(得分:3)

我们一直在应用@ SedateAlien的答案部分启发的后期构建过程,现在我的雇主已经有3年了,我不得不说如果你处理的是更多的话而不仅仅是几个品牌。

这不完全是在公园散步,但一旦你让一切都工作得当,它将为你节省大量时间,并保持你的项目干净简单。

这是我们采取的高级方法:

  1. 使用单个目标设计和构建您的应用项目,该目标将充当您的原型,即仅仅是一个品牌或者#34; unkinned"变种。您将针对此目标执行大部分开发,因此请确保它具有足够的基础资源以便完全可用。
  2. 建立品牌资源"存储库某处可容纳不同的品牌资产。我们使用" brand.config"在每个品牌的目录中存档,其中包含各种品牌特定信息,如应用名称,捆绑ID等,以及将被换成捆绑包的各种知名资源文件。
  3. 设置构建服务器(我们使用Jenkins)或shell脚本,以基于构建的原型.app执行品牌化过程。品牌流程的工作原理如下:

  4. 将整个原型.app软件包复制到新目录并删除所有代码签名。

  5. 使用Plistbuddy根据brand.config中的参数修改捆绑包的plist。
  6. 使用品牌资源目录中的资源交换捆绑包中的知名资源(图片等)。
  7. 将应用程序可执行文件编码并捆绑并压缩成.ipa。
  8. 最棘手的部分无疑将是代码签名。您可能需要使用权利文件,并且还必须确保在构建计算机上正确识别和安装证书。

    如果遇到问题,请不要放弃。我承诺 可能!我将尝试帮助解决人们在评论中遇到的任何具体问题,但了解它已经有一段时间了,因为我积极开发了这个,所以我不能太详细。

    我还应该提到我们从未对App Store提交有关此流程的任何问题,我们提交了一个批次的应用程序(每次更新都超过100个)。

答案 3 :(得分:1)

我为公司做了同样的事情,所以我可以与你分享我是如何做到的。我和你在一起,直到你说Jenkins,因为我使用了Xcode,但也许你可以使它工作。

基本上,您创建了一个包含在“皮肤”应用程序项目中的库项目。皮肤包括任何特定于应用程序的图像,plist,甚至可能包括一些方法。您可以创建一个.h文件,该文件由框架使用,其中一个类可以修改对象,函数或全局变量。此文件的标头包含在库中以允许构建库。

例如,假设它有“extern UIImage * mainBackgroundImage;”,你在库中引用它(即你检索它以便显示)。

“skin”应用程序当然有.m(或.c)文件来解析你在.h文件中承诺的所有公共项目。

在Xcode中,您将创建一个库项目。您可以在每个“皮肤”项目中包含它(请记住,您需要在“构建阶段”窗格中依赖库,并确保该库包含在链接阶段。如果您在库中使用类别,则需要通过在每个目标的项目中为Link Flags添加一个特殊行来强制加载库。

您可以在半小时内构建一个带有两个项目的测试工具来说服自己,这样可以正常工作。

答案 4 :(得分:1)

值得注意的是,任何遇到这种困境的人都会在iOS7中引入资产目录,这使得这个问题在XCode中很容易解决。我有多个目标的项目和资产目录,可以在一个地方轻松处理资源,自定义构建设置和代码签名问题。不仅如此,当Apple引入新的外形(例如iPhone 6+)时,很容易看出哪些资产目录不是最新的(例如,缺少iPhone 6+启动屏幕)。非常灵活。假设您有12个需要换肤的目标,7个是学校,5个是工作场所。创建一个名为SchoolMedia的新资产目录,另一个名为WorkMedia。在每个目录中添加一个名为main_symbol的图像集。在您的XIB中,使用main_symbol。让SchoolMedia成为学校目标的成员,WorkMedia成为工作目标的成员。将根据目标显示右main_symbol。排列是无穷无尽的,XCode的可视化界面可以让您轻松了解正在发生的事情(即使过去有点无法管理)