modulemap的作用
 
modulemap 文件是用来解决 C,Object-C,C++ 代码在 Swift 项目中集成的问题的。
在 Swift 项目中,如果需要使用 C,Object-C 或者 C++ 代码,需要将相应的头文件和源文件导入到项目中,并且需要手动管理它们之间的依赖关系。导致项目结构复杂,管理困难。
为了解决这个问题,可以使用 modulemap 文件来定义模块,将 C,Object-C 或者 C++ 代码组合成一个模块,然后在 Swift 项目中直接导入该模块。

文档中的说明:

As Bridging-Header can help us in App Target and App Test Target, not in static library or dynamic libraries to use the Objective C / C APIs into Swift classes, modulemap can help us here.
 
在Swift项目中使用Objective C / C APIs的方式
Swift使用Objective C / C源码时:在App工程中OC文件可以通过放置在Bridging-Header文件中让Swift其他文件引用。
Swift使用Objective C / C的静态库,动态库时:在framework静态库,动态库中OC文件可以通过给framework添加module.modulemap让Swift通过“import xxx模块”方式对文件进行引用的。
Module导入方式优点
 
传统.h文件导入的问题
对于基于C语言而来的其他语言,在导入时,都是导入.h文件,开发者目测很难区分到底导入的是C,C++,还是OC
编译性能问题
编译器在预编译阶段碰到import xx.h后,会将xx文件复制,替换到xx.h这个位置。如果一个.h文件中包含了多个其他.h文件,其他.h文件中又相互包含时,则会出现相同的代码多次被替换。
另外模块多次导入时,还易出现宏定义替换不完全,错误替换的问题(如:当前文件有方法A,它包含的文件中存在了宏定义A,那改如果替换呢)
module导入方式
每个模块都是一个完全隔离的个体。
当模块第一次被import时,编译器会根据modulemap把它里面的模块编译成预编译模块(Precompiled Module)pcm文件,并将其在本地缓存,里面包含了模块的所有API信息。
当第二个模块被import导入时,编译器会直接找这个模块被编译后的缓存二进制文件。提升了编译效率。
Module模块的使用方式
普通导入方式:
#import <MyModule/MyModule-Swift.h>
模块导入语法: 
@import MyModule;
Swift导入模块的方式
import MyModule
使用模块导入方式就需要framework下包含module.modulemap文件,modulemap指明了framework中的头文件的逻辑结构和如何映射成模块。
在使用 MyModule 模块时,就可以直接导入MyModule模块文件,而不需要手动逐个添加里面的子模块。
Module模块语法
//给Swift项目用的
framework module MyModule {
umbrella header "MyModule.h" // headers.h 和 module.modulemap 必须在同一group下,否则需要配置 `header "/??/headers.h"`
header "headers.h" requires objc
export * //将子模块都导出到主模块
module * { export * } //将当前目录下所有的头文件(包括umbrella header中包含的每个头文件和其他header "headers.h"头文件)都导出成子模块
} //给OC项目用的,需要支持objc语言环境
module MyModule.Swift {
header "MyModule-Swift.h"
requires objc
}
module * { export * } :将当前目录下所有的头文件打包成一个模块,
export * 表示:将其他模块中的所有头文件都导出到当前模块中
export * 和 module * { export * } 同时使用表示将当前目录下所有的头文件打包成一个模块,并将其他模块中的所有头文件也导出到当前模块中。
header 命令:表示将指定的头文件添加到当前模块中。
umbrella header 命令:表示将指定的头文件视为一个 umbrella header,该头文件中包含了其他多个头文件的接口。这个头文件中包含了其他多个头文件的接口,因此可以使用 export * 命令将所有接口都导出到当前模块中。
framework module XXXX 定义了一个 framework 语义的模块
requires objc 说明:导入模块的编译单元要支持OC语言环境
header "headers.h" 说明:将头文件aa.h映射为模块
 
模块声明
[framework] module module-id [extern_c] [system] {
module-member
}
extern_c:表示moduel中的C代码可以被C++使用,相当于添加了extern 'C'这个声明。
 
常见Module目录结构
Name.framework/
Modules/module.modulemap framework 的模块映射
Headers/ 包含了 framework 中的头文件
PrivateHeaders/ 包含了 framework 中私有的头文件
Frameworks/ 包含嵌入的其它 framework
Resources/ 包含额外的资源
Name 指向共享库的符号链接
 
另外
Xcode创建的APP和库默认都是支持Moduel导入的,如果不支持可以手动在在 Build Settings 中,Defines Module 的设置为 YES,进行支持。
参考文章:
https://juejin.cn/post/7139724115157450765
https://zhuanlan.zhihu.com/p/602783297
https://www.jianshu.com/p/ce49d8f32f77

modulemap的使用方法的更多相关文章

  1. 用swift开发framework时采用OC混编的解决方案

    随着swift ABI的稳定,越来越多的开发者开始使用swift语言开发项目,但是由于大部分工具库也还是使用OC写的,因此我们不得不需要在项目中采用swift与oc混编. 在开发app项目时,swif ...

  2. javaSE27天复习总结

    JAVA学习总结    2 第一天    2 1:计算机概述(了解)    2 (1)计算机    2 (2)计算机硬件    2 (3)计算机软件    2 (4)软件开发(理解)    2 (5) ...

  3. mapreduce多文件输出的两方法

    mapreduce多文件输出的两方法   package duogemap;   import java.io.IOException;   import org.apache.hadoop.conf ...

  4. 【.net 深呼吸】细说CodeDom(6):方法参数

    本文老周就给大伙伴们介绍一下方法参数代码的生成. 在开始之前,先补充一下上一篇烂文的内容.在上一篇文章中,老周检讨了 MemberAttributes 枚举的用法,老周此前误以为该枚举不能进行按位操作 ...

  5. IE6、7下html标签间存在空白符,导致渲染后占用多余空白位置的原因及解决方法

    直接上图:原因:该div包含的内容是靠后台进行print操作,输出的.如果没有输出任何内容,浏览器会默认给该空白区域添加空白符.在IE6.7下,浏览器解析渲染时,会认为空白符也是占位置的,默认其具有字 ...

  6. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  7. [C#] C# 基础回顾 - 匿名方法

    C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...

  8. ArcGIS 10.0紧凑型切片读写方法

    首先介绍一下ArcGIS10.0的缓存机制: 切片方案 切片方案包括缓存的比例级别.切片尺寸和切片原点.这些属性定义缓存边界的存在位置,在某些客户端中叠加缓存时匹配这些属性十分重要.图像格式和抗锯齿等 ...

  9. [BOT] 一种android中实现“圆角矩形”的方法

    内容简介 文章介绍ImageView(方法也可以应用到其它View)圆角矩形(包括圆形)的一种实现方式,四个角可以分别指定为圆角.思路是利用"Xfermode + Path"来进行 ...

  10. JS 判断数据类型的三种方法

    说到数据类型,我们先理一下JavaScript中常见的几种数据类型: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Functi ...

随机推荐

  1. 详解 APISIX Lua 动态调试插件 inspect

    作者罗锦华,API7.ai 技术专家/技术工程师,开源项目 pgcat,lua-resty-ffi,lua-resty-inspect 的作者. 原文链接 为什么需要 Lua 动态调试插件? Apac ...

  2. Docker高级

    一.Docker安装企业级开发应用 1.Docker搭建MySQL主从 (1) 创建master主机MySQL docker run -p 3307:3306 --name mysql-master ...

  3. 【Redis】-使用Lua脚本解决多线程下的超卖问题以及为什么?

    一.多线程下引起的超卖问题呈现1.1.我先初始化库存数量为1.订单数量为0 1.2.开启3个线程去执行业务 业务为:判断如果说库存数量大于0,则库存减1,订单数量加1 结果为:库存为-2,订单数量为3 ...

  4. 2020-10-06:java中垃圾回收器让工作线程停顿下来是怎么做的?

    福大大答案2020-10-06: 简单回答:安全点,主动式中断. 中级回答:用户线程暂停,GC 线程要开始工作,但是要确保用户线程暂停的这行字节码指令是不会导致引用关系的变化.所以 JVM 会在字节码 ...

  5. 2022-01-02:给定两个数组A和B,长度都是N, A[i]不可以在A中和其他数交换,只可以选择和B[i]交换(0<=i<n), 你的目的是让A有序,返回你能不能做到。

    2022-01-02:给定两个数组A和B,长度都是N, A[i]不可以在A中和其他数交换,只可以选择和B[i]交换(0<=i<n), 你的目的是让A有序,返回你能不能做到. 答案2022- ...

  6. 【工作随手记】deaklock排查

    生产环境当中还没真正遇到过死锁的问题.有些疑似死锁的问题,后来经过排查也只是其它问题导致的.所以通过jstack到底怎样排查死锁问题有点疏忽了.这里作个记录. 模拟一个死锁 顺便复习一下. 死锁的产生 ...

  7. 2015年蓝桥杯C/C++大学B组省赛真题(星系炸弹)

    题目描述: 在X星系的广袤空间中漂浮着许多X星人造"炸弹",用来作为宇宙中的路标. 每个炸弹都可以设定多少天之后爆炸. 比如:阿尔法炸弹2015年1月1日放置,定时为15天,则它在 ...

  8. Jackson前后端开发模式必备json利器

    前言 json是我们现代互联网程序最常用的交互格式,是否你在工作中会遇到前端说字段不一致需要改的需求,是否遇到过数据库字段名与javaBean的规范不同,是否遇到过json与javaBean相互转换时 ...

  9. R 语言柱状图示例笔记

    由于微信不允许外部链接,你需要点击文章尾部左下角的 "阅读原文",才能访问文章中链接. 一.基础柱状图 1. barplot 命令 基于barplot基础柱状图颜色.方向及分组的绘 ...

  10. Redis系列14:使用List实现消息队列

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ...