之前开发了一个 IM 通讯软件在公司内部使用,现在需要将 IM 以 SDK 的方式集成到另外一个 OA 应用中。对比了下两个工程,OA 应用是属于比较老旧的那种,全部以 OC 实现,并且依赖的第三方库比较老旧而且都是以代码集成方式管理,甚至对部分三方库做了修改。IM 是通过 Pods 进行第三方依赖库的管理,和 OA 共用若干库。由于是要求 IM 提供 SDK,加上 OA 不愿意修改他们的工程,所以我们只能以 SDK 的方式给他们提供Framework包。考虑到可能有的代码冲突,我们决定一些 两方都使用的UI 相关的库,在要求 UI 统一的情况下,拿出OA 的源码打包成 framework,双方共用。其余的非交叉的库各自引用各自的互不干扰,OA 使用源码集成,IM 使用 Pods 集成 framework。
IM 工程是 OC 和 Swift 混编的,在 Application 工程中,对于这种混编的解决方案也很简单,只要增加桥接头文件就可以了。但是在 Framework 工程中,是不需要桥接文件的。那在 Framework 工程中如何做到混编的呢?
1、首先当你新建一个 Framework 工程时,Xcode 的工程模板是会自动生成极简情况下的工程文件,其中有一个非常重要的文件,$(TARGET_NAME).h 文件。这个文件是作为 Framework 将内部方法暴露给外部调用的一个 Public 入口头文件,系统帮你默认生成的。
2、新建 Podfile,如下编写:
这里需要注意,使用 Swift 的 Framework 都必须在 Podfile 中写上 use_frameworks!原因如下两个:
A、用CocoaPods 导入swift 框架 到 swift项目和OC项目都必须要 use_frameworks!
B、使用 dynamic frameworks,必须要在Podfile文件中添加 use_frameworks!
2、选择 PROJECR/TARGET -> Build Settings -> Allow non-modular includes in Framework Modules -> YES
注意: Project 和 Target 需要同时设置。
因为新版本的 Pods 的方式是将第三方库制作成Dynamic Frameworks,相当于在 MyFramework 中引用别的 Framework,需要告诉编译器允许这种行为。
3、将 Swift 文件中用到的 OC 文件的头文件包含到 MyFramework.h 中,并且将对应的头文件放到 Target -> Buid Phases -> Headers -> Public 中。这里需要注意的是,就算你在 Swift 代码中直接引用第三方库的方法,你也不需要将第三方库的头文件引用放到 MyFramework.h 中,只需要将你自己用到的 OC 头文件放入其中即可。原因第四点会讲。
4、编译工程,你会收到编译成功的通知。进入 Products 目录,你会发现 Products 目录下有如下几个文件:
你会发现编译结果为自己的 Framework 和第三方的 Framework,包括 Pods 生成的引用 Framework(只是引用,并没有将第三方库打包到其中)。如果你要向别人提供 MyFramework.framework ,别人是无法编译通过的,因为MyFramework.framework中仅包含它自己的源码而不包括第三放库的,因为苹果禁止在Dynamic Frameworks使用 Framework。所以你需要将所有的 Framework 都交付给第三方,除了 Pods生成的Framework。至此MyFramework 生成结束。
你可能会有疑问,如此引入会不会有编译问题。那这里可以探讨下。
一般集成第三方库的方式有如下三种:
A、直接将第三方库的源码集成到工程中;
B、将第三方库打包成 Static Library 集成到工程中;
C、将第三方库打包成 Framework 集成;
其中 A、B 两种方式是一样的,都需要链接第三方库的源码,只是 Static Library 是提前编译好了。如果第三方工程采用 A 方式集成第三方库,正如我遇到的情况,就算我们使用了相同的第三方库,也不会发生错误,因为他使用本地文件,头文件的引用方式和使用 Framework 的引用方式是不一样的,可以说两者是在不同的 NameSpace 中,编译器在编译和链接的过程中并不会发生错误。甚至 MyFramework 中可以使用与第三方相同的文件和类名,只要他在使用时文件中不同时引用MyFramework的头文件。
最后,鉴于Dynamic Frameworks 的优势,本人还是不推荐使用 AB 两种方式集成第三方库,除非万不得已。
以下为参考资料:
pods 使用方法:http://www.jianshu.com/p/ad2e37e741bb
http://www.samirchen.com/create-a-framework/
https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
http://stackoverflow.com/questions/24175697/how-do-i-use-cocoapods-in-an-embedded-framework
http://www.tuicool.com/articles/Q3q6ry
https://guides.cocoapods.org/syntax/podfile.html
https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/CreationGuidelines.html#//apple_ref/doc/uid/20002254-BAJHGGGA