随着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. springcloud 08 Hystrix图形化DashBoard

    #1.构建一个服务监控模块 ##1.1创建模块cloud-consumer-hystrix-dashboard9001 ##1.2pom文件依赖 <dependencies> <!- ...

  2. PowerToys 微软效率工具包 使用教程

    今天给大家介绍一款 非常实用的微软工具包 里面包含 快捷键的使用 颜色选择器 键盘管理器 屏幕标尺 鼠标实用工具等众多高效工作的功能 还是蛮出彩的 下载 PowerToys⇲ 安装教程 1.双击文件运 ...

  3. windows C++

    #include <Windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar ...

  4. Centos7下areaDetector IOC的编译后记

    https://github.com/EPICS-synApps/support/releases synApps出新版了,本文发文时的最新版为:R6-2 Centos7下areaDetector I ...

  5. 00-DLL劫持&C语言远程加载shellcode

    0x01 杀软拦截检测规则引导-DLL劫持上线 准备工具 cs vs2019 dll劫持工具:https://bbs.pediy.com/thread-224408.htm 极速PDF:https:/ ...

  6. playwright 实现高亮、is_visible 等源码修改

    一. 前言 高亮是什么? 在ui自动化中可以执行js来让某个页面元素高亮,比如背景颜色.字体颜色.边框颜色等发生改变,以此更加方便执行的时候点了哪一步操作.(如果有不清楚怎么实现的可以转到我的介绍se ...

  7. JZOJ 3737. 【NOI2014模拟7.11】挖宝藏

    \(\text{Solution}\) 当 \(h=1\) 时显然是斯坦纳树板子,最方案必然是树形的 \(h > 1\) 时,考虑在每一层新建一个状态表示上一层宝藏全部挖完到这层某个点的答案 同 ...

  8. .net webapi+jwt demo

    一.新建.net   webapi程序 二.nuget包搜索jwt,点击安装 三.在model文件夹下建立三个主要类: public class AuthInfo    {        /// &l ...

  9. LeetCode-382 链表随机结点

    来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/linked-list-random-node 题目描述 给你一个单链表,随机选择链表的一个节点, ...

  10. left join(一)

    例表aaid adate1 a12 a23 a3 表bbid bdate1 b12 b24 b4 两个表a,b相连接,要取出id相同的字段select * from a inner join b on ...