随着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混编的解决方案的更多相关文章

  1. Swift数独游戏优化——C++与OC混编、plist自动生成

    一.为什么要C++与OC混编? 在我之前的数独游戏中涉及到的数独游戏生成算法是参考的网上其他人的算法,是利用C++来实现的.   但是在我的例子中我发现这样存在一定的局限性: 1.我是利用Termin ...

  2. iOS开发之swift与OC混编出现的坑,oc中不能对swift的代理进行调用,不能访问swift中的代理,swift中的回调方法

    1. Swift与oc混编译具体怎么实现,这儿我就不重复讲出了,网上有大把的人讲解. 2. 在swift与OC混编的编译环境下, oc类不能访问swift创建类中的代理? 解决方法如下: 在代理的头部 ...

  3. iOS8开发~Swift(五)Swift与OC混编

    一.概要 首先看<The Swift Programming Language>中提到"Swift's compatibility with Objective-C lets y ...

  4. Swift & OC 混编 浅析

    转载自:http://www.infoq.com/cn/articles/wangyi-cartoon-swift-mixed-practice?utm_campaign=rightbar_v2&am ...

  5. swift c++ oc 混编

    http://www.tuicool.com/articles/QZNrErM iOS 里面 Swift与Objective-C混编,Swift与C++混编的一些比较 时间 2015-03-23 23 ...

  6. Swift与OC混编

    OC调用Swift的方法:添加 import "xxxx-Swift.h" 头文件即可 Swift调用OC的方法:需要建立桥接: xxxx-Bridging-Header.h 头文 ...

  7. cocoapod Podfile use frameworks swift/oc混编 could not build module xxx

    前置: 知名的pod: AFNetworking 我自己的pod:  AFNetworking+RX  3.1.0.18 里面有一段代码是: #import <Foundation/Founda ...

  8. iOS 静态类库 打包 C,C++文件及和OC混编

    iOS 静态类库 编译 C,C++ 我们都知道,OC 原生支持C, 在 创建的 OC类的 .m 里面,可以直接编写C的代码: 同样 Xcode 也支持 OC ,C++的混编,此时,我们通常把OC创建的 ...

  9. iOS之 C++与oc混编

    声明:本文只是随笔,自己做个笔记方便以后查阅如要转载,注明出处.谢谢! 2016年第一篇随笔!!! 由于最近要搞一个项目用到c++的一些api所以要混编,于是就记录下这个过程中的一些细节上的东西! O ...

  10. swift和 oc 混编2-备

    在Swift语言出现之前,开发iOS或OS X应用主要使用Objective-C语言,此外还可以使用C和C++语言,但是UI部分只能使用Objective-C语言. 选择语言 Swift语言出现后,苹 ...

随机推荐

  1. Nginx02 Nginx的的目录结构、基本工作原理、基本配置文件介绍

    1 Nginx目录结构 1.1 简要介绍 [root@localhost ~]# tree /usr/local/nginx /usr/local/nginx ├── client_body_temp ...

  2. Sentinel熔断与限流

    1.简介 在线文档: https://sentinelguard.io/zh-cn/docs/system-adaptive-protection.html 功能: 流量控制 速率控制 熔断和限流 和 ...

  3. 另类数据获取法-eax法

    有些基址非常难追 所以我们用一个另类的方法来追一下 复杂的汇编代码 ------------------ call 0x****** mov esi,eax; mov ***, dword ptr d ...

  4. dvwa靶场

    brute force LOW 输入账号密码直接抓包就行 接着ctrl+i传输到intruder模块中 为需要爆破的加上 §,不爆破的不加 选择攻击类型为Cluster bomb,选择username ...

  5. 【CTO变形记】整体系统思维-从现象到本质

    前言:我们的⼤脑⾥的认知不是⼀块⽩板,⽽是写满着密密麻麻对这个世界形成的各种观念.信念.塞满了对事物的各个表象,我们脑中的表象世界,对应着外部世界的各种事物. 如果感觉本篇看起来有点不适应,可以看看之 ...

  6. Vulhub 漏洞学习之:Discuz

    Vulhub 漏洞学习之:Discuz 目录 Vulhub 漏洞学习之:Discuz 1 Discuz 7.x/6.x 全局变量防御绕过导致代码执行 1.1 漏洞利用过程 2 Discuz!X ≤3. ...

  7. CCRD_TOC_2008年第11期

    中信国健临床通讯 2008年第11期(总第24期) 目 录   脊柱关节炎 1. 一项多中心.大型.随机.双盲.对照试验证实依那西普治疗AS的疗效优于柳氮磺吡啶 Braun J, et al. ACR ...

  8. C# 时间各种格式

    1.1 取当前年月日时分秒 currentTime=System.DateTime.Now; 1.2 取当前年 int 年=currentTime.Year; 1.3 取当前月 int 月=curre ...

  9. 【论文笔记】UNet

    语义分割的U-Net网络结构Unet是2015年诞生的模型,它几乎是当前segmentation项目中应用最广的模型.Unet能从更少的训练图像中进行学习,当它在少于40张图的生物医学数据集上训练时, ...

  10. C#的闭包捕获变量与英语中Nice to meet you的联系

    看标题有种"意大利面与42号混凝土"放在一起说的感觉,实际上,就是. 闭包捕获变量 我们都知道在C#里,闭包捕获的是变量,而不是变量值本身 每个Task在运行的时候,发现i的值是3 ...