10

我正在创建一个通用应用程序,它将为不同的客户提供不同的构建。该应用程序对于每个客户来说都是 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,因此不可能为此使用框架。

感谢您的任何反馈。

(PS 构建系统将使用 Jenkins 自动化)。

4

5 回答 5

9

您只需要在项目中创建多个目标并为每个目标(客户/品牌)拥有资源文件夹。以下是如何做到这一点:

  1. 创建两个新的资源文件夹 Resources_Customer1 b. 资源_客户2
  2. 将适当的资源复制到相应的文件夹中
  3. 选择项目 -> 目标
  4. 复制目标
  5. 在 [Copy Build Resources] 中自定义资源名称,使其指向适当的
    客户/品牌
  6. 根据所选目标测试和验证适当的目标运行。

希望这可以帮助!

于 2012-07-31T23:05:04.537 回答
6

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

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

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

本质上,我们尝试尽可能地将皮肤与代码本身分开。我们发现,任何涉及 Xcode 本身的解决方案都需要手动从开发人员的头皮上自行去除头发。

于 2012-07-31T23:23:12.653 回答
3

在我现在的雇主大约 3 年的时间里,我们一直在应用一个部分受到 @SedateAlien 回答的启发的后期构建流程,我不得不说,如果您处理的不仅仅是几个品牌,这绝对是要走的路。

这并不完全是在公园里散步,但一旦你最终让一切正常工作,它将为你节省大量时间,同时让你的项目保持干净和简单。

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

  1. 使用将作为原型的单一目标来设计和构建您的应用程序项目,即只是一个单一品牌或“未剥皮”变体。您将针对此目标执行大部分开发,因此请确保它具有足够的基础资源以完全可用。
  2. 在某处建立一个“品牌资源”存储库来保存不同的品牌资产。我们在每个品牌的目录中使用一个“brand.config”文件,其中包含各种品牌特定的信息,如应用名称、捆绑包 ID 等,以及将交换到捆绑包中的各种知名资源文件。
  3. 设置构建服务器(我们使用 Jenkins)或 shell 脚本,以基于构建的原型 .app 执行品牌塑造过程。品牌流程如下:

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

  5. 使用 Plistbuddy 根据 brand.config 中的参数修改捆绑包的 plist。
  6. 将捆绑包中的知名资源(图像等)替换为品牌资源目录中的资源。
  7. 对应用程序可执行文件进行协同设计,并将其打包并压缩为 .ipa。

最棘手的部分无疑是代码设计。您可能需要使用权利文件,并且还必须确保证书被正确识别并安装在您的构建机器上。

如果遇到问题,请不要放弃。我保证可能的!我会尽力帮助解决人们在评论中遇到的任何具体问题,但我知道我已经有一段时间没有积极开发这个了,所以我不能说得太详细。

我还应该提到,我们在 App Store 提交的过程中从未遇到任何问题,而且我们提交了很多应用程序(每次更新 100 多个)。

于 2016-04-25T22:25:07.447 回答
1

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

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

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

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

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

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

于 2012-07-31T23:02:36.423 回答
1

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

于 2015-06-02T01:02:55.347 回答