和Swift模块化混编方案

背景

目前的工程是纯OC的工程,并且已经使用了Cocoapods实现模块化管理。为了与时俱进,现需要引入swift到工程,并且能够让cocoapods管理的Swift模块与OC模块相互调用。

混编方案

1.添加空的Swift文件到主工程,比如叫XXMain.swift

注意:主工程必须要有一个Swift文件,使得Xcode支持Swift编译。

创建的时候会弹出是否需要创建 Bridging-Header桥接文件,这里可以不用创建。模块化做的比较好的情况下,主工程模块中添加Bridging-Header文件其实也用不上。

cocoapods自动管理modulemap用于暴露swift类以及引入其他OC类。

swift moya 转模型 swift 模块化_静态库

2.修改iOS最低支持的版本号为12.3

注意:swift5开始 ABI才稳定,而从iOS 12.3开始 系统内包含swift5。

创建的时候会弹出是否需要创建 bridge桥接文件,这里不需要创建。创建bridge文件之后,可能会导致cocoapods模块下的swift文件报 找不到OC类的错误。

cocoapods自动管理modulemap用于需要暴露的swift类以及引入其他OC类。

swift moya 转模型 swift 模块化_swift_02

3.引入OC到Swift模块

注意:我的Swift代码会根据业务分成不同的模块,通过cocoapods去管理。此时需要在模块中添加一个h头文件用于引入OC类,文件头的名称要与模块 “名称一致” ,比如pods模块名称为XwjModule,那么你需要创建一个XwjModule.h文件夹用于包含需要引入的OC头文件。

如果没有同名头文件,会导致无法调试Swift模块代码

swift moya 转模型 swift 模块化_swift_03

4.Podfile和PodSpec

注意:
Podfile中需要使用use_modular_headers!方式兼容OC与Swift混编

PodSpec文件中source_files中除了包含swift文件,还要包含第3步中创建的头文件。

Podfile文件

swift moya 转模型 swift 模块化_静态库_04

PodSpec文件

swift moya 转模型 swift 模块化_swift moya 转模型_05

二进制化Swift模块

注意:上述四个步骤已经可以完成OC与Swift的混合开发了,如果此刻不想把Swift源码暴露出来,那么就需要将Swift模块二进制化。

1.合并静态库

通过上述混编方案,我们已经可以进行正常开发,此时,我们分别在"Debug 模拟器模式" / "release 真机模式"执行build,
可以得到Xcode编译的所有的a静态库文件。找到其中Swift模块对应的静态库,并且执行lipo -create命令合并静态库。

swift moya 转模型 swift 模块化_swift moya 转模型_06

2.头文件

找到静态库依赖的头文件,以SwiftJSSDKModule为例子,Xcode编译之后会生成libSwiftJSSDKModule.a静态库,
同时还会生成SwiftJSSDKModule-Swift.h 和 SwiftJSSDKModule-umbrella.h文件。
SwiftJSSDKModule-Swift.h实际上是Xcode把Swift代码翻译成了OC代码,使得其他的OC代码可以引用其对象
SwiftJSSDKModule-umbrella.h 实际上是包含了Swift模块自己需要引入的OC头文件

3.二进制化的PodSpec

二进制化后,我们只需要包含a静态库、SwiftJSSDKModule-Swift.h 和 SwiftJSSDKModule-umbrella.h即可完成模块配置了。
这里分享一个小技巧,使用一个宏IS_BINARY 和 {s.name}_SOURCE 用于动态的切换二进制化模式和代码模式。具体方式如图:

swift moya 转模型 swift 模块化_静态库_07

最后

对于OC与Swift混编的处理方式就分享到这里 还有其他疑问的同学可以在留言,我们可以一起讨论。下篇打算分享下 Swift与OC交互之ModuleMap的作用