Swift和OC混编开发
# 13.Swift和OC混编开发
# 目录介绍
- 04.混编之桥接文件
- 4.1 建立头文件桥接
- 4.2 混编中找不到头文件
- 05.混编开发调用技巧
- 5.1 OC调用Swift
- 5.2 Swift调用OC
- 5.3 遇到的坑说明
- 06.Framework混编
- 6.1 背景说明一下
- 6.2 头文件导入方式
- 6.3 配置modulemap
# 04.混编之桥接文件
# 4.1 建立头文件桥接
建立一个 Header 头文件,将它放置在自己想要放置的文件下。比如在混编App开发的时候,应用层用Swift,一些基础库用OC,当Swift想去调用OC可以采用头文件桥接这种方式。
在APP开发中,swift和OC文件可以通过桥接的方式互相调用。特别是swift语言调用OC时,把OC文件直接拖到工程中,xcode会自动生成桥接文件。
但是在编写framework文件时会发现拖动到工程中,不但没有生成桥接文件反而报了错;解决此类问题使用module.modulemap文件显得特别方便。
# 4.2 混编中找不到头文件
报错:三方库头文件 import 报错 '**.h' file not found with include
#import <MJExtension.h>
解决方案:这也是一类问题,使用不规范的写法导入基础组件头文件,在混编过程中就会直接报错,修改 import 写法即可解决:
#import "MJExtension.h"
//或
#import <MJExtension/MJExtension.h>
2
3
# 05.混编开发调用技巧
# 5.1 OC调用Swift
OC想要调用Swift,Swift类必须用@objc + public修饰,否则无法访问。继承自NSObject或其子类
在OC文件#import <项目名/项目名-Swift.h>文件,这个文件是编译器自动生成的。比如:#import "ProductName/ProductModuleName-Swift.h"
# 5.2 Swift调用OC
在 ProductModuleName-Bridging-Header.h 桥接文件中引入Swift需要调用的OC头文件
在这个桥接文件里面引用你想暴露给Swift调用类的头文件。说明:这个桥接文件需要自己手动创建
# 5.3 遇到的坑说明
坑1: 在OC类中引用Swift编译之后的头文件,必须采用"ProductName/ProductModuleName-Swift.h"方式,使用ProductModuleName-Swift.h方式,会提示找不到该文件
坑2: 如果未设置Objective-C Bridging Header,引用ProductName/ProductModuleName-Swift.h头文件之后依然无法在OC类中调用Swift类
因为设置Objective-C Bridging Header后,才会编译Swift类到ProductModuleName-Swift.h中。设置Objective-C Bridging Header后Swift类被翻译成OC类,才可以被OC调用
坑3: 设置Objective-C Bridging Header后编译报错using bridging headers with framework targets is unsupported,解决方案就是修改ProductModuleName.h这个文件名称为其他名称,比如:ProductModuleNameHeader.h
# 06.Framework混编
# 6.1 背景说明一下
随着swift ABI的稳定,越来越多的开发者开始使用swift语言开发项目,但是由于大部分工具库也还是使用OC写的,因此我们不得不需要在项目中采用swift与oc混编。
在开发app项目时,swift与oc混编其实很容易,xcode会自动为我们建立一个桥接文件,这样我们就很容易的在swift中调用oc的方法或类对象。
但是在开发framework的时候,xcode不会为我们建立这个桥接文件,因此我们在framework中也就不能采用桥接的方式进行混编了。
# 6.2 头文件导入方式
第一种:也是最简单的一种,就是将oc的头文件暴露出来,并在framework的头文件中导入。(缺点:我们不想对外暴露的类或方法,不得不暴露出去)
具体参考:https://www.cnblogs.com/zbblog/p/16228840.html
# 6.3 配置modulemap
第二种:配置modulemap,这个方法可以避免我们不得不对外暴露我们的oc类。
第一步:在项目中创建module.modulemap文件,具体内容如下:
//这里我们定义了一个 WecardPaySDK 的模块,也就是提供给swift导入的模块名称。
module WecardPaySDK {
//使用了一个umbrella header文件"HeaderPrivate.h",该文件用于导入Swift和Objective-C的私有头文件。
umbrella header "HeaderPrivate.h"
// 这里的路径是相对于module.modulemap的所在目录
header "WecardPay.h"
//在这个模块中,使用了export关键字,表示将模块中的所有内容都导出,使其可供其他模块或应用程序使用。
export *
}
2
3
4
5
6
7
8
9
10
11
12
第二步:配置Swift Compiler - Search Paths Import Paths。这里是为了告诉编译器,我们自定义的module所在路径,这里指定了项目的根目录:$(SRCROOT)
具体参考:https://blog.csdn.net/qq26983255/article/details/89107699
# 参考
- iOS 学习笔记:https://github.com/xiusl/ObjectiveC_Day
- OC与Swift实现framework内混编:https://juejin.cn/post/7343691521600471040?searchId=20250422111304F5DECFF620425F268EC9
- Swift与OC混编:https://juejin.cn/post/6964610478219722765?searchId=20250422111304F5DECFF620425F268EC9
- Swift和OC混编:https://juejin.cn/post/7031738486084337700
- OC-Swift 混编踩坑总结:https://juejin.cn/post/7070430587701444638