让我们考虑以下场景:应用程序“MyApp”正在使用由Propretary MySDK.framework提供的SDK。反过来,MySDK依赖于开源库,如AFNetworking和RESTKit。 为了分发MySDK,开发人员需要提供所有依赖项,例如,RESTKit需要AFNetworking 1.x并且它与2.0版本不兼容。
在预框架场景中,MySDK使用的库将全部嵌入到框架的二进制文件中,并且显然是一起发布的。 如果MyApp需要使用AFNetworking或其他库,这些将嵌入应用程序的二进制文件中。如果是MyApp和MySDK之间的共享库,代码将被复制并嵌入到MyApp的二进制文件和MySDK的二进制文件中。因此,如果MyApp需要AFNetworking 2.x,则不会发生冲突,因为每个二进制文件都会嵌入自己的版本。
输入框架。 使用框架,每个库都被编译为单独的.framework,并在运行时链接到使用它的代码。为了分发具有所有依赖关系的MySDK,框架包在MySDK.framework / Frameworks目录中包含所有依赖关系作为“sub”-Frameworks。 同样,MyApp将在MyApp.app/Frameworks中包含MySDK框架以及swift库和MyApp特有的所有其他依赖项。
如果将这样的应用程序上传到iTunes connect,服务器会拒绝它,原因如下:“验证错误:无效的捆绑包。 [MySDK.framework path]中的包包含不允许的文件'Frameworks'“。 看起来iTunes只接受第一级Frameworks,然后直接嵌入应用程序包中,但我无法在任何地方找到该规则。
另一种方法是展平Framework层次结构并将所有MySDK依赖项与MySDK.framework一起发布,让MyApp开发人员将它们包含在App的捆绑包中,并使用复制框架阶段。 这会产生一个不同的问题:我们现在的情况是每个库只能有一个版本,所以如果MySDK需要AFNetworking 1.x,那么应用程序将无法使用AFNetworking 2.x,因为所有框架都在同样的水平,没有名称空间。 为了解决这个问题,一种解决方案是为AFNetworking创建一个版本化框架并包含两个版本。不幸的是,这意味着我们每次出现时都需要为每个版本的库维护一个不同的包。 Cocoapods不支持版本化框架,因此我们也会阻止MySDK用户使用它。即使在这种情况下,我们如何在编译时指定二进制文件应链接到哪个版本的框架? MySDK.framework不再是一个独立的单元,它的稳定性取决于外部操作,如将正确的依赖项导入应用程序。这听起来不太好。
有哪些选择? 我真的想在我们的代码上使用.frameworks / @ import,因为那是Apple的标题,但我觉得现在唯一的麻烦免费路径是使用现在过时且效率低下的静态库。