【问题标题】:Build Multiple iOS Apps out of a Framework从一个框架中构建多个 iOS 应用程序
【发布时间】:2014-01-28 20:03:52
【问题描述】:

我有一个项目,我需要从一个基本应用程序中构建一些应用程序。 对于“子应用程序”,它会更改应用程序的 API 凭据、字体、大小、颜色和一些功能。

所以我更改了我的应用程序,以便我可以轻松地添加功能、更改颜色……通过更改简单的字符串常量来更快地构建新应用程序。


我认为最好的解决方案是向此 XCode 项目添加多个目标,并使用条件编译器标志设置应用程序的各个设置

#ifdef AppTarget1
qr_reader = YES;
#endif

但问题是,将来会有多个版本的框架可用。因此,当基于旧框架更新应用程序时,我们总是必须进行调整以使用框架的新版本(如果有),并且我们无法控制框架版本等。

一个目标也是让我们的开发人员使用简单的 Podfile 轻松构建新的应用程序。


所以下一个想法是创建一个框架项目,然后将其包含在我们的主应用程序中的 CocoaPods 中。我按照本教程进行操作:http://chariotsolutions.com/blog/post/using-cocoapods-to-manage-private-libraries/

在我包含框架的 MainApp 中,MainApp-AppDelegate 类是 Framework-AppDelegate 类的子类。

@interface MainApp_AppDelegate : FrameworkAppDelegate

我在 MainApp_AppDelegate 中设置我覆盖的所有基于应用程序的设置的方法。

@implementation MainApp_AppDelegate

-(void)initSettings {
    qr_reader = YES;
}

@end

它就像一种魅力,但我对图像有一个问题。 AppFramework 包含 Image training.png 和 image y.png。

在主应用程序 xyz 中,我决定 Image training.png 看起来不适合此应用程序,所以我只想更改它(y.png 我想要包含在框架中的版本)。我将 x.png 放入 Main App Ressources 文件夹,但在编译并运行后,我看到了 AppFramework 项目中包含的图像。

是否有任何方法可以改变这种行为或更好的方法来创建框架?

【问题讨论】:

  • 您是如何访问应用中的图像的?
  • 与:[UIImage imageNamed:@"training.jpg"]

标签: objective-c xcode frameworks


【解决方案1】:

正在发生的事情是 Cocoapods 在您的应用完成复制他的之后将其资源复制到最终的 .app 捆绑包中。所以你的training.jpg 会被你的框架覆盖。

构建阶段顺序

正如@masam 所说,您需要重新排序项目的构建阶段,以便在 Cocoapods 资源之后复制应用程序的资源。

(注意“Copy Bundle Resources”现在位于列表中“Copy Pods Resources”下)

强制资源复制

不幸的是,这还不够,因为 Xcode 的构建系统(试图做到?)智能并且不会复制(或在源文件的情况下重新编译)目标是“最新”。对于像图像这样的静态资源,最新意味着目标路径(在最终的 .app 包中)比源路径(在 Xcode 项目中)更新。

因此,如果您现在尝试运行您的应用,您会发现没有任何变化。 Xcode 不会复制 training.jpg,因为它在 .app 中已经存在并且更新。

您需要让 Xcode 认为 .app 中的资源已经过时并且需要更新。为此,请在“Copy Pods Resources”和“Copy Bundle Resources”之间添加一个新的“Run Script Build Phase”:

脚本应将资源的修改日期设置为较早的日期,以强制 Xcode 复制您应用的资源。 touch 完成这项工作:

find ${TARGET_BUILD_DIR} -name 'training.jpg' -exec touch -ct $(date -v-1d "+%Y%m%d%H%M.%S") {} \;

我们使用date -v-1d "+%Y%m%d%H%M.%S" 将资源的修改日期设置为昨天。

Xcode 现在将用应用程序的图像覆盖框架的图像。

管理目标资源

同样,正如@masam 所说,不要忘记仅将资源添加到正确的目标。

例如。

这里,DummyApp会使用app镜像,而DummyApp2会使用framework镜像。

结论

tl;dr:尽可能避免这种情况。

  • 对于项目的新手来说,乍一看不可能知道为什么有些目标是用一个文件而不是另一个文件构建的;
  • 根据您要覆盖的框架的资源类型,您可能需要维护“重置资源修改时间”脚本(可能通过使find 更具包容性,例如find ${TARGET_BUILD_DIR} -name '*.png');李>
  • 更多的是主观意见:我建议不要使用自己的资源从框架中隐藏资源。

关于 one-target-per-app-flavor 事情:

请记住,您对一个目标的构建阶段所做的每次修改都不会影响其他目标的构建阶段。您需要单独编辑每个目标。因此我之前的如果可以避免就不要这样做

我完全理解需要多个目标来基于相同的代码库构建多个应用程序,但 Xcode 在管理大量目标方面非常糟糕。从一个正在开发具有 65 个不同目标的相当大的应用程序(1k+ 文件和 大量 依赖项)的人那里得到它:这是一场噩梦。

.pbxproj 基本上会随着您的目标数量(在我的情况下为 25MB)而增长,并且每次在 Xcode 中完成项目修改时,您都会获得沙滩球。并且由于每个目标都是独立管理的,因此每次您需要例如。添加/删除编译标志,您将需要更新每个目标,一个。经过。一个。 (或者您将使用sed/awk/whatever 编辑.pbxproj“手动”,这更快,但有风险......但很有趣:))。

哦...我提到合并冲突了吗?

【讨论】:

  • 谢谢,答案很详细。我知道我们将来还会用这个框架构建许多应用程序(可能有 100 个或更多)。那你会推荐我什么?基于不同的目标构建应用程序或使用这种框架风格的方式构建它?如果我使用框架,那么我将所有图像直接包含在 App 目标中(而不是在框架目标中)?
  • 如果您在框架中拥有大部分“核心”代码,并且每个目标中只有配置或较小的修改,那么这可能会很好。我的项目有问题,因为每个目标都自己编译每个文件,导致 pbxproj 中的大量重复(但不在源文件中)。不过,我不确定 Cocoapods,因为它可能会为每次修改增加大量开销,并且如果框架仅由该项目使用,则几乎没有什么好处。这取决于您想要实现的目标。
  • 在子项目(SubTargets)中只会更改配置变量/一些图像,没有额外的代码。因此,如果我正确理解您的最后一条评论,您建议使用 Subfragment(Cocoapods)而不是 Targets 来解决这个问题? (当框架更新可用时,我需要更新所有应用程序)
  • 补充:还是把Targets和Fragment结合起来最好?我的框架包含在一个包含所有子应用目标的应用程序中,因此在更新所有子应用程序时,我只需要编译一次核心框架。
  • @Nilesh 我在%S 之前添加了一个点.,这似乎解决了这个问题。再次感谢您的反馈!
【解决方案2】:

这可能是由于您的构建阶段(项目 -> 构建阶段)中的特定顺序造成的。默认情况下,它会先复制 bundle 资源,然后再复制 Pods 资源(覆盖您在主应用中拥有的资源)。

您可以将“Copy Pods Resources”的顺序拖到“Copy Bundle Resources”上方。

您还必须通过单击图像资源 -> 文件检查器 -> 目标成员身份来验证主项目中包含的图像资源是否具有正确的目标成员身份。应该检查您正在编译的目标。

【讨论】:

    【解决方案3】:

    复制你的目标!?

    我通过这种方式构建的最后一个应用程序为每个目标使用不同的包标识符。 然后只需对您的捆绑 ID 进行测试,以便以编程方式进行不同的设置。

    NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      相关资源
      最近更新 更多