用swift开发framework时采用OC混编的解决方案
随着swift ABI的稳定,越来越多的开发者开始使用swift语言开发项目,但是由于大部分工具库也还是使用OC写的,因此我们不得不需要在项目中采用swift与oc混编。
在开发app项目时,swift与oc混编其实很容易,xcode会自动为我们建立一个桥接文件,这样我们就很容易的在swift中调用oc的方法或类对象。
但是在开发framework的时候,xcode不会为我们建立这个桥接文件,因此我们在framework中也就不能采用桥接的方式进行混编了。
framework中实现混编的方式有两种:
第一种:也是最简单的一种,就是将oc的头文件暴露出来,并在framework的头文件中导入。(缺点:我们不想对外暴露的类或方法,不得不暴露出去)


这样一来,我们就可以在swift中直接引用oc的类了

第二种:配置modulemap,这个方法可以避免我们不得不对外暴露我们的oc类。
(1):在项目中创建module.modulemap文件,具体内容如下:
module MyObjcFramework {
header "oc/MyObjc.h" // 这里的路径是相对于module.modulemap的所在目录
export *
}
这里我们定义了一个MyObjcFramework的模块,也就是提供给swift导入的模块名称。
header是该模块的头文件,如果你需要了解关于module的更多详细信息,可以查看这篇文章,或者Clang Module's documentation。
(2):配置Swift Compiler - Search Paths Import Paths:

这里是为了告诉编译器,我们自定义的module所在路径,这里指定了项目的根目录:$(SRCROOT),当然你也可以指定的更具体,像下面这样:

然后我们就可以在swift中导入我们自定义的module,从而引用oc类。
import Foundation
import MyObjcFramework // 导入自定义模块 public func testPrint(_ str: String) {
let objc = MyObjc()
objc.printStr(str)
}
以上两种方法解决了我们在使用swift开发framework时与oc混编的问题,一般常用第二种方式,不过依具体情况决定。
另外说一下swift开发framework与OC的区别,使用swift开发framework导出的framework文件中的Modules目录下多出一个xxx.swiftmodule包,这个是swift提供的公共组件接口定义。
我们看一下这个包里都有哪些文件:

swiftdoc应该是api文档的描述。swiftmodule定义了MyKit组件的api公共接口。
Project里的文件如下:

另外当你在Build Settings中设置Build Libraries for Distribution = YES时,再次Build你的framework后,在xxx.swiftmodule包中会多出一个swiftinterface文件。
这个是swift5.1之后对swiftmodule的补充,它们的目的都是为了实现编译一个向后兼容的二进制库。
下面是重点,重点,重点。
在合并模拟器与真机的二进制库时,不能像OC那样简单的将合并后的二进制文件替换就可以了,因为swift中模块定义的公共接口都是在swiftmodule中定义的,而它们也是区分架构的,因此你需要将合并后的二进制文件替换之外,将不同架构的swiftmodule和swiftinterface文件拷贝到当前framework/Modules/xxx.swiftmodule包中。
当然还有另外一种合并多平台架构的方式,那就是xcframework,但是我却在这里遇到了一个问题,那就是在swift于OC混编时使用modulemap时生成的xcframework,导入到实际app工程时报错,下面是具体的错误:

MyHandler就是在swift编写的framework工程中利用module.modulemap对OC文件的一种引入方式,对应的modulemap如下:
module "MyHandler" {
umbrella header "./src/oc/MyTextHandler.h"
export *
module * { export * }
}
使用MyHandler的地方:
import UIKit
import DrFlexLayout_swift
import MyHandler public class MViewController: UIViewController { let text: String
let handler: MyTextHandler public init(text: String) {
self.text = text
self.handler = MyTextHandler(prefix: "T")
super.init(nibName: nil, bundle: nil)
}
}
framework的工程可以正常编译通过,但是在合并成xcframework后,将xcframework导入到app工程后编译就会包上面的错误。
这个问题我暂时没办法解决,希望知道的解决方法朋友在下面留言告诉我一下,不胜感激!
难道就不能使用xcframework了吗?当然是可以使用了,前面我们提到过在swift编写的framework中混编OC或c时,还有另一种方法,那就是将OC或c的头文件暴露在framework工程的头文件中,这样生成的xcframework就可以正常使用了,但是缺点自然是有的,这也是没办法的办法。
感谢@ronzheng的帮助,以上的问题已经得到解决。解决办法是将import MyHandler替换成@_implementationOnly import MyHandler即可。我遇到的这个问题也有其他人同样遇到了,可以看这里查看,关于@_implementationOnly的作用没有官方解释,不过我推测就是将被修饰的导入的模块私有化,在使用中我同样遇到了一些其他问题,在评论中有提到。因此在使用@_implementationOnly导入内部私有模块时,最好放在内部类中使用。
用swift开发framework时采用OC混编的解决方案的更多相关文章
- Swift数独游戏优化——C++与OC混编、plist自动生成
一.为什么要C++与OC混编? 在我之前的数独游戏中涉及到的数独游戏生成算法是参考的网上其他人的算法,是利用C++来实现的. 但是在我的例子中我发现这样存在一定的局限性: 1.我是利用Termin ...
- iOS开发之swift与OC混编出现的坑,oc中不能对swift的代理进行调用,不能访问swift中的代理,swift中的回调方法
1. Swift与oc混编译具体怎么实现,这儿我就不重复讲出了,网上有大把的人讲解. 2. 在swift与OC混编的编译环境下, oc类不能访问swift创建类中的代理? 解决方法如下: 在代理的头部 ...
- iOS8开发~Swift(五)Swift与OC混编
一.概要 首先看<The Swift Programming Language>中提到"Swift's compatibility with Objective-C lets y ...
- Swift & OC 混编 浅析
转载自:http://www.infoq.com/cn/articles/wangyi-cartoon-swift-mixed-practice?utm_campaign=rightbar_v2&am ...
- swift c++ oc 混编
http://www.tuicool.com/articles/QZNrErM iOS 里面 Swift与Objective-C混编,Swift与C++混编的一些比较 时间 2015-03-23 23 ...
- Swift与OC混编
OC调用Swift的方法:添加 import "xxxx-Swift.h" 头文件即可 Swift调用OC的方法:需要建立桥接: xxxx-Bridging-Header.h 头文 ...
- cocoapod Podfile use frameworks swift/oc混编 could not build module xxx
前置: 知名的pod: AFNetworking 我自己的pod: AFNetworking+RX 3.1.0.18 里面有一段代码是: #import <Foundation/Founda ...
- iOS 静态类库 打包 C,C++文件及和OC混编
iOS 静态类库 编译 C,C++ 我们都知道,OC 原生支持C, 在 创建的 OC类的 .m 里面,可以直接编写C的代码: 同样 Xcode 也支持 OC ,C++的混编,此时,我们通常把OC创建的 ...
- iOS之 C++与oc混编
声明:本文只是随笔,自己做个笔记方便以后查阅如要转载,注明出处.谢谢! 2016年第一篇随笔!!! 由于最近要搞一个项目用到c++的一些api所以要混编,于是就记录下这个过程中的一些细节上的东西! O ...
- swift和 oc 混编2-备
在Swift语言出现之前,开发iOS或OS X应用主要使用Objective-C语言,此外还可以使用C和C++语言,但是UI部分只能使用Objective-C语言. 选择语言 Swift语言出现后,苹 ...
随机推荐
- 力扣每日一题2023.1.16---1813. 句子相似性 III
一个句子是由一些单词与它们之间的单个空格组成,且句子的开头和结尾没有多余空格.比方说,"Hello World" ,"HELLO" ,"hello w ...
- .net 多地点计算中心点
1.需求产生 快到周末了,几个远在各个区的朋友想要聚餐,为了照顾到彼此的距离,决定计算一下所有人的中心点,至此需求产生,下面开始编写代码. 2.编写代码 1)新建一个控制台程序 在NuGet程序包管理 ...
- xshell连接时显示“服务器发送了一个意外的数据包。received:3,expected:20“问题的解决方法
xshell连接时显示"服务器发送了一个意外的数据包.received:3,expected:20"问题的解决方法 解决方法:在/etc/ssh/sshd_config最后增加以下 ...
- appium连接手机 adb调试 app自动化
一. 工具准备 jdk,java环境必备. android sdk,要使用内置的Android debug bridge,简称adb,调试手机用. appium,提供自动化服务,app自动化的核心库. ...
- JZOJ 2474. 【GDKOI 2021普及组DAY2】我的世界
题解 这题很明显发现一个点到另一个点,必然最多只有一个进入下界的点和一个出来的点 分类讨论入点和出点的位置 要么都在 \(u->lca\) 或都在 \(lca->v\) 或分别有一个 那就 ...
- CCRD_TOC_2008年第7和第8期(ACR专辑)
中信国健临床通讯 2008年第7.第8期合刊 ACR专辑 目 录 强直性脊柱炎 1. 一项随机对照和开放性延伸期试验:TNF拮抗剂治疗放射学前中轴型脊柱关节病 Boettger MK, et al ...
- 【C学习笔记】day3-3 编写程序数一下 1到 100 的所有整数中出现多少个数字9
#include <stdio.h> int main() { int cou=0; for (int i = 1; i <= 100; i++) { if (i % 10 == 9 ...
- shiyansi
#include <stdio.h> #include <stdlib.h> #define N 1000 int fun(int n,int m,int bb[N]) { i ...
- [后端-python实战总结]-chapter1-python基础01
1.1 week 1 > 密码秘文: import getpass username = input('username:') passwd = getpass.getpass('passwd: ...
- oracle收缩表和表空间
oracle shrink space收缩表 segment shrink分为两个阶段: 1).数据重组(compact):通过一系列insert.delete操作,将数据尽量排列在段的前面.在这个过 ...