学计算机的那个

不是我觉到、悟到,你给不了我,给了也拿不住;只有我觉到、悟到,才有可能做到,能做到的才是我的.

0%

ObjC和Swift混编

概述

随着Xcode 11、Swift 5.0的发布,Swift目前已经实现了ABI稳定及模块稳定,并且Swift runtime和标准库已经植入系统中,而且苹果新出文档都用Swift,Sample Code也是Swift,可以看出Swift是苹果扶持与研发的重点方向。

对于新App来说,可以直接用纯Swift进行开发,而对于老App来说,绝大部分以前都是用OC开发的,因此Swift/OC混编是一个必然面临的问题。

ObjC和Swift混编

OC/Swift 调用 Swift,最终通过 Swift Module 进行,而 Swift 调用 OC 时,则是通过 Clang Module,当然也可以通过 Clang Module 进行 OC 对 OC 的调用。

同一工程内的混编

宿主工程利用桥接文件(Bridging-Header.h)进行混编

  • Swift访问Obje-C
    只需要在桥接文件中(Bridging-Header.h)导入需要暴露给Swift模块的Objective-C类,即可在Swift中访问相应Objective-C的类和方法

  • Objective-C访问Swift
    在Objective-C类中导入ProductName-Swift.h,即可访问Swift中暴露给Objective-C的类和方法

利用cocoapods包管理工具,进行二/三方库混编

  • Swift访问Obj-C
    用Swift Module系统,需要用到的Objective-C类用import xxx进行引用,即可在Swift中访问相应的Objective-c的类和方法

  • Objective-C访问Swift
    在Objective-c类中导入ProductName-Swift.h,即可访问Swift中暴露给Objective-C的类和方法

Module系统

LLVM Module系统

苹果在 2012 年 11 月提出 LLVMModule 系统,简单讲就是用树形的结构化的描述来取代以往 #include ,例如传统的#include 现在变成 import std.io

意义:

  • 语义上完整描述了一个框架的作用
  • 提高编译时的可扩展性,同一模块只需编译或导入一次,避免了头文件的多次引用、解析
  • 减少碎片化,每个模块只处理一次,环境的变化不会导致不一致

modulemap文件

modulemap文件就是对一个框架,一个库的所有文件的结构化描述。默认文件名是module.modulemap

Swift Module

SwiftModule 可以将 Swift 解析后生成对应的 modulemap 和 umbrella.h 文件,SwiftModule 增加对编译器版本的依赖,编译产物与编译器 和 Swift 版本有关。如果想要实现 Swift 和 Objective-C 的互相访问,需要 Objective-C 库,以及对应的 umbrella.h 和 modulemap 支持。其中动态库 framework 是 Xcode 支持配置并生成 header,静态库 .a 需要自己编写对应的 umbrella.h 和 modulemap。即库之间无论何种语言实现,均需要封装为 LLVM Module 来相互访问。

Cocoapods配置

use_ modular_ headers! 配置将三方库构建成静态库,或者 use_frameworks! 配置将三方库构建成动态库时,在编译产物中都会生成一个 modulemap 和 module umbrella.h 文件

use_ modular_ headers!是 Cocoapods 1.5.0 引入的配置,目的是为了满足 Xcode 9 以后支持的 Swift Static Libraries ,将 Swift Pods 构建成为静态库

  • 如果你的 Swift Pod 依赖于 Objective-C,那么你需要为这个 Objective-C 库启用 modular_headers
  • 对于 pod 开发者可以在 podtargetxcconfig 内添加 ’DEFINES_MODULE’=>‘YES’,对于使用者在 podfile 内添加 use _modular _headers!
  • 在 podspec 中通过 modular_headers => true 配置特定的 pod

参考

Swift和Objective-C混编在有赞移动的实践
从预编译的角度理解Swift与Objective-C及混编机制
Swift与Objective-C混编时,我们是如何将编译时间优化了35%

一方:(一方包,一方库),一般指的是本项目或者本工程中的类和方法、接口等。
二方:(二方包,二方库),一般指的是公司内部的依赖库,公司内部其他项目发布的jar包,如公司项目平台的核心依赖包。
三方:(三方包,三方库),一般指的是外部的开源库或开源项目贡献的jar, 比如apache、google、Ali等发布的依赖