iOS UmbrellaHeader
Lexical or Preprocessor Issue - Umbrella header for module 'xxx' does not include header 'xxx.h'
framework 的文件明明被主工程引用了,但是在编译的时候依旧抛出上面的警告。
一、什么是 umbrella header?
参考官方文档《Introduction to Framework Programming Guide》,可以了解到 Framework 区分Standard Framework 和 Umbrella Framework。但是并没有找到官方文档有对 Umberlla framework 给出明确的定义。在官方文档《Anatomy of Framework Bundles》章节中, 找到三段比较合理说明 Umbrella Framework 的话:
Umbrella frameworks add minor refinements to the standard framework structure, such as the ability to encompass other frameworks
The structure of an umbrella framework is similar to that of a standard framework, and applications do not distinguish between umbrella frameworks and standard frameworks when linking to them. However, two factors distinguish umbrella frameworks from other frameworks. The first is the manner in which they include header files. The second is the fact that they encapsulate subframeworks.
Physically, umbrella frameworks have a similar structure to standard frameworks. One significant difference is the addition of a Frameworks directory to contain the subframeworks that make up the umbrella framework.
字面上的意思应该是在标准的 Framework 做了一些改良的工作,使其可以嵌套包含 Framework。在物理结构上,Umbrella Framework 只在包含头文件的方式以及是否包含子 Framework 和普通的 Framework 存在区别。
那么引用头文件的地方又有什么区别呢? 还是参考官方文档引用:
For most frameworks, you can include header files other than the master header file. You can include any specific header file you want as long as it is available in the framework’s Headers directory. However, if you are including an umbrella framework, you must include the master header file. Umbrella frameworks do not allow you to include the headers of their constituent subframeworks directly. See Restrictions on Subframework Linking for more information.
简单翻译一下: 普通的 Framework 可以通过引用对应的 heaedr 文件而不是 Master Header File 去引用需要使用的类,只需要对应的 header 头文件在 Headers 文件夹下暴露,并没有强制要求引用 Master Header File。Umbrella Framework 要求必须要引用 Master Header File,并且头文件中不能直接引用子 Framework 的东西。
上述描述已经说了 Umbrella Framework 一定要引用 Master Header File,而 Umbrella Framework 的 Master Header File 就是 Umbrella header 文件。
官方说明中只有强制规定一定要引用 Umbrella Header 文件,但是却没有说能不能单独引用 Umbrella Framework 的其他头文件呢? 我们可以自己试验一下:
- 在 Umbrella Framework 新建一个 testObject 类,分别产生了 testObject.h 和 testObject.m 文件。
- 打开 Framework 配置文件,在 Build Phases的Headers 里的 Public 目录下,将 testObject.h 文件添加进去。
- Build Framework 看是否报错。
- 在主工程中调用初始化 testObject 对象,看编译是否报错。
执行结果:
- 步骤3: 没有编译报错, 但是报出了 Lexical or Preprocessor Issue - Umbrella header for module 'STDemoUI' does not include header 'testObject.h'的警告。
- 步骤4: 执行正常。
总结一下:
- Standard Framework 不能包含 Sub Framework;Umbrella Framework 可以包含子 Framework;
- Standard Framework 可以直接引用需要使用的头,也可以通过引用 Master Header file 来引用需要使用的类;Umbrella Framework 需要通过引用 Master Header File(Umbrella Header) 来引用需要使用的类;
二、规范的写法
Umbrella Framework 默认会创建一个同名 .h 文件做为 Umbrella Header 文件。规范的写法当然是遵从默认的模式,将所有需要暴露的头文件都写在 Umbrella Header 文件中。
例如: STDemoUI.framework 工程包含了 STClassOne、STClassTwo 和 STClassThree 三个类。
STDemoUI 会生成一个默认的伞头文件(直译 Umbrella Header)STDemoUI.h。假设该 framework 的三个类均需要在外部调用使用,则 STDemoUI.h 需要将三个类的引用均写入伞头文件中。
// STDemoUI.h
// ...
#import <STDemoUI/STClassOne.h>
#import <STDemoUI/STClassTwo.h>
#import <STDemoUI/STClassThree.h>
在需要调用的主工程中, 仅仅只要将 Umbrella Header 引用即可调用所有在 Umbrella Header 中包含的类了。
// 在主工程需要应用的类中包含Umbrella Header
#import <STDemoUI/STDemoUI.h>
三、重命名 umbrella header
如果大家都遵从默认的 Umbrella Framework 的写法,在同名头文件中写需要暴露的引用头文件,那么就不需要考虑怎么重命名 Umbrella header 了。
很多时候,理想和现实是有差距的,程序员写代码多数是在二次接手进行开发的。假设公司的前辈已经将 Framework 的同名文件用作了一个逻辑类, 给同名文件创建了 .m 文件, 并已经书写了逻辑并应用了各个工程里面去了。那么显然迁移头文件功能代码是不可能的,因为很多依赖该 Framework 的业务部门都需要针对库进行代码优化。
在这种不能将同名文件作为 Umbrella header 的情况下,我们又不想通过 Public 强制暴露头文件的情况下(不写在 Umbrella Header 中会有警告)。我们就需要对 Umbrella Header 进行指定了。
- 指定 Umbrella Header 入口在哪里呢? - 在工程全局搜索 umbrella 关键字 - Failed
- 在Build Settings里搜索umbrella关键字 - Failed
- 在打包好的 STDemoUI.framework 中搜索 umbrella 关键字 - Success
 - 双击点开 STDemo.framework,内容如下:  - 初略看名称可以推测出每个文件以及文件夹所承担的作用: - _CodeSignature:保存签名相关文件
- Headers:framework 暴露的所有头文件
- Info.plist:描述了该 framework 所包含的项目配置信息
- UmbrellaFramework:编译后的核心库文件
- Modules:模块相关文件夹, 目测只包含了 module.modulemap 文件
- Frameworks:包含的子 framework
 - 我们在 module.modulemap 文件中找到了 umbrella 关键字。文件内容如下: - framework module STDemoUI {
 umbrella header "STDemoUI.h"
 export *
 module * { export * }
 }
 - 原来 Framework 的 umbrella header 是在这个位置被指定的,但是这个已经是编译好的工程, 我们总不能每次编译好了再进到包里面修改下。既然我们已经找到 umbrella header 是在 module 中去指定,那么我们就用 module 作为关键字再去 Build Settings 里重新搜索下。 - 这回在 Kernel Module 和 Packaging 中均找到了 Module 关键字,在 Packaging 标签中,有一项 Module Map File 属性,看名字应该是用来指定 modulemap 文件的。  
- 指定 Modulemap 文件 - 创建一个新的 .h 文件,如:STHeader.h。将所有需要暴露的头文件均写入 STHeader.h
- 创建一个新的 modulemap 文件,如:stdemoalt.modulemap
- 在新的 modulemap 中指定 umbrella header - framework module STDemoUI {
 umbrella header "STHeader.h"
 export *
 module * { export * }
 }
 
- 在 framework 的 Build Settings 中的 Module Map File 指定新建的 modulemap 文件。 
- CMD+B 编译,打开 framework 包中的 Module 文件夹,看是否包含了新指定的 modulemap。 
 
抛出两个疑问:
- Module 是什么?
- 如果 Defines Module 指定为 NO, 那会发生什么事情呢?
四、总结
本文简单的梳理了官方文章关于 Umbrella Framework 和 Umbrella Header 的介绍说明,产生警告的原因是没有引用 umbrella header 或者暴露头没有写在 umbrella header 中。在 umbrella header 被已使用的前提下,本文提供了一种通过重命名 Umbrella Header 文件的方式来消除警告的解决方案。
虽然引用警告可以被消除,但是建议大家还是采用规范的做法:尽量不要在同名头文件中写业务逻辑代码, 用同名文件作为 Umbrella 库的 Master Header File。
五、内容来源
iOS - Umbrella Header在framework中的应用
iOS UmbrellaHeader的更多相关文章
- iOS可视化动态绘制连通图
		上篇博客<iOS可视化动态绘制八种排序过程>可视化了一下一些排序的过程,本篇博客就来聊聊图的东西.在之前的博客中详细的讲过图的相关内容,比如<图的物理存储结构与深搜.广搜>.当 ... 
- 【疯狂造轮子-iOS】JSON转Model系列之二
		[疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ... 
- 【疯狂造轮子-iOS】JSON转Model系列之一
		[疯狂造轮子-iOS]JSON转Model系列之一 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 之前一直看别人的源码,虽然对自己提升比较大,但毕竟不是自己写的,很容易遗 ... 
- iOS总结_UI层自我复习总结
		UI层复习笔记 在main文件中,UIApplicationMain函数一共做了三件事 根据第三个参数创建了一个应用程序对象 默认写nil,即创建的是UIApplication类型的对象,此对象看成是 ... 
- iOS代码规范(OC和Swift)
		下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ... 
- JS调用Android、Ios原生控件
		在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时, ... 
- 告别被拒,如何提升iOS审核通过率(上篇)
		iOS审核一直是每款移动产品上架苹果商店时面对的一座大山,每次提审都像是一次漫长而又悲壮的旅行,经常被苹果拒之门外,无比煎熬.那么问题来了,我们有没有什么办法准确把握苹果审核准则,从而提升审核的通过率 ... 
- Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)
		本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ... 
- Summary of Critical and Exploitable iOS Vulnerabilities in 2016
		Summary of Critical and Exploitable iOS Vulnerabilities in 2016 Author:Min (Spark) Zheng, Cererdlong ... 
随机推荐
- 一篇文章带您读懂Map集合(源码分析)
			今天要分享的Java集合是Map,主要是针对它的常见实现类HashMap进行讲解(jdk1.8) 什么是Map核心方法源码剖析1.文档注释2.成员变量3.构造方法4.put()5.get() 什么是M ... 
- PyCharm+git+码云实现project版本控制
			1.安装git https://git-scm.com/downloads 2.PyCharm中配置 3.申请码云 4.PyCharm中安装码云插件 右键选择,重启Pycharm. 重新打开PyCha ... 
- npm发布包的那些事
			npm发包的那些事 最近一直在研习关于node的知识,发布包虽然是最基础的一点,但由于一些地方的不注意很容易发生错误,我整理了我可能出现过的一些发布包的过程中的一些error,现在分享给大家: 正确的 ... 
- seo搜索优化技巧01-seo外链怎么发?
			在seo搜索优化中,seo外链的作用并没有早期的作用大了.可是高质量的外链对关键词的排名还是很重要的.星辉信息科技对seo外链怎么发以及seo外链建设中的注意点进行阐述. SEO外链如何做 SEO高质 ... 
- 教你高效使用数据可视化BI软件创建医院卫生耗材运营监控大屏
			灯果数据可视化BI软件是新一代人工智能数据可视化大屏软件,内置丰富的大屏模板,可视化编辑操作,无需任何经验就可以创建属于你自己的大屏.大家可以在他们的官网下载软件. 本文以医院卫生耗材运营监控大屏 ... 
- Apache Tomcat 文件包含漏洞(CVE-2020-1938)
			2月20日,国家信息安全漏洞共享平台(CNVD)发布了Apache Tomcat文件包含漏洞(CNVD-2020-10487/CVE-2020-1938).该漏洞是由于Tomcat AJP协议存在缺陷 ... 
- windows服务搭建与删除简单介绍
			安装windows服务: 1 VS的开发命令使用管理员权限打开, 2 installutl.exe /servicename="服务名称" "服务地址" 卸载 ... 
- Simulink仿真入门到精通(五) Simulink模型的仿真
			5.1 模型的配置仿真 由各种模块所构建的可视化逻辑连接,只是模型的外在表现,模型仿真的核心驱动器是被称作解算器(Solver)的组件,相当于Simulink仿真过程的心脏,驱动着模型仿真,它在每一个 ... 
- 使用StreamHttpResponse和FileResponse下载文件的注意事项及文件私有化
			为什么需要编写下载视图方法? 你或许知道,我们上传的文件默认放在media文件夹中的,且Django会为每个上传的静态文件分配一个静态url.在模板中,你可以使用{{ mymodel.file.url ... 
- ASP.NET 开源导入导出库Magicodes.IE 完成Excel图片导入导出
			Magicodes.IE Excel图片导入导出 为了更好的根据实际功能来迭代,从2.2的里程碑规划开始,我们将结合社区的建议和意见来进行迭代,您可以点此链接来提交您的意见和建议: https://g ... 
