用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语言出现后,苹 ...
随机推荐
- TCP/IP协议(3): Wi-Fi(IEEE 802.11) 协议 —— 构成无线局域网的基本协议
TCP/IP协议(3): Wi-Fi(IEEE 802.11) 协议 -- 构成无线局域网的基本协议 关于 Wi-Fi(IEEE 802.11) 协议 关于 IEEE 802.11 IEEE 802. ...
- 基于FLink实现的实时安全检测(一段时间内连续登录失败20次后,下一次登录成功场景)
研发背景 公司安全部目前针对内部系统的网络访问日志的安全审计,大部分都是T+1时效,每日当天,启动Python编写的定时任务,完成昨日的日志审计和检测,定时任务运行完成后,统一进行企业微信告警推送.这 ...
- Vue 计算属性与普通的函数有什么区别?
计算属性的优势 计算属性的作用是计算复杂的逻辑,并返回一个结果,提供给模板多次使用:只要依赖的响应式数据没有改变,计算属性就不会重新执行,而是直接返回它存储的缓存.所以,节省不必要的开销. 模板语法的 ...
- Canvas:绘制圆形
函数 arc(x, y, radius, startAngle, endAngle, counterclockwise) 参数名 描述 x.y 圆心坐标轴 radius 圆的半径 startAngle ...
- 把MyBatis当项目一样,讲透源码的技术书籍!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 为啥?因为这些年,就很少有人能自主意识到,如何提升编码质量! 但讲屁话没有用,想学好编程突破阶 ...
- pat乙级:模拟链表问题(汇总,包含所有pat中链表题目分析)
更新:优化文章结构,增加了部分内容如(1110区块反转)和自己代码和他人代码分析.看完你就懂了 转载请注明出处和链接地址:(https://www.cnblogs.com/ahappyfool/p/1 ...
- php正方形图片转成成圆形图片-GD
/** * 剪切图片为圆形 * @param $picture 图片数据流 比如file_get_contents(imageurl)返回的东东 * @return 图片数据流 */ private ...
- No.1.9
项目样式补充 精灵图(场景:项目中将多张小图片,合并成一张大图片,这张大图片称之为精灵图) (优点:减少服务器发送次数,减轻服务器的压力,提高页面加载速度) 精灵图的使用步骤:1.创建一个盒子,设置盒 ...
- tdlib成功编译版本20230205(java)
tdjni是java本地调用接口dll文件夹下的三个动态链接是供tdjni调用的使用时这三个加到系统环境变量里 编译文件在本人的文件里,可以下载
- Centos 6.5 iptables 端口白名单设置
iptables -I INPUT -p tcp --dport 8888 -j DROPiptables -I INPUT -s 10.9.145.101 -p tcp --dport 8888 - ...