iOS开发中的头文件引用

头文件引用一般都会随着项目规模变大而可读性变差。当大部分精力花费在业务上往往容易忽视头文件的使用和规范。整理下常见的头文件疑问和知识点,希望能给正在寻找这方面答案的人一些帮助。

一、基本头文件引用方式

说到OC中的头文件引用,不得不说三个基本的引用方式(#include、#import、@class) 和 预编译头文件(.pch)。

#include:

  • 是编译指令,也是C/C++中的头文件引用方式,#include是简单的复制粘贴,将目标.h文件中的内容一字不落地拷贝到当前文件中,并替换掉这句#inclued。(但GCC现在为C/C++做了特殊处理使得#import可以被编译)

#import:

  • 是OC中的头文件引用方式,本质功能是和#include是一样的。但是多了一个功能:避免头文件重复引用带来的编译错误。(例如:B、C同时通过#include引用A;D又同时引用B、C;相当于D通过B、C重复引用了A)

如果想深究,import的实现是通过#ifndef一个标志进行判断,然后在引入后#define这个标志,来避免重复引用的。

想象一下它长这样:

  #ifndef MyFile_h

  #define MyFile_h

  // Some code

  #endif

@class:

  • 仅仅是声明一个类名,并不会包含类的完整声明。
  • 能解决循环包含的问题:当两个类文件有循环依赖关系 ( A 引用 B , B 引用 A ) 时,需要用 @class

.pch预编译头文件:

  • 一般情况下,在OC中使用#import足矣。不过这样的拷贝和复制对编译速度和代码可读性真的好吗?

import的实质还是拷贝粘贴,这样就带来两个问题:

  • 当引用关系很复杂 或者 一个头文件被非常多的实现文件引用时,编译时引用所占的代码量就会大幅上升(因为被引用的头文件在各个地方都被copy了一遍);
  • 公用头文件遍布代码之中将导致头文件很长。

为了解决这些问题,C系语言引入了预编译头文件(PreCompiled Header),将公用的头文件放入预编译头文件中预先进行编译,然后在真正编译工程时再将预先编译好的产物加入到所有待编译的Source中去,来加快编译速度。比如iOS开发中Supporting Files组内的.pch文件就是一个预编译头文件,默认情况下,它引用了UIKit和Foundation两个头文件--这是在iOS开发中基本每个实现文件都会用到的东西。

当然预编译头文件也不应该乱用误用,否则将导致工程中随处可用本不该能访问的代码。编译器无法给出准确的问题报错,增加了编译出错的可能性。

预编译头文件的使用标准:
// include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
// 包含系统基础库文件 或者 项目中经常使用到但不经常修改的特定头文件

二、OC中的Modules和它的头文件引用

  • 关于Modules的由来,可以追溯到2012年的 LLVM Developers' Meeting。简单总结下Modules的出现是可以保留预编译头文件的一个优势和解决几个问题:
    保留优势:预编译处理,提高编译速度。
    解决问题:引用滥用;难以定位编译问题;难以维护;

Modules相当于将框架进行了封装,然后加入在实际编译之时加入了一个用来存放已编译添加过的Modules列表。如果在编译的文件中引用到某个Modules的话,将首先在这个列表内查找,找到的话说明已经被加载过则直接使用已有的,如果没有找到,则把引用的头文件编译后加入到这个表中。这样被引用到的Modules只会被编译一次,但是在开发时又不会被意外使用到,从而同时解决了编译时间和引用泛滥两方面的问题。

我们看看.moudulemap的定义:

  framework module LDPMChart {
       umbrella header "LDPMChart-umbrella.h"
       export *
       module * { export * }
  }

这个Module定义了首要头文件(LDPMChart-umbrella.h),需要导出的子modules(所有),以及需要link的框架名称(LDPMChart)。需要指出的是,现在Module还不支持第三方的框架,所以只有SDK内置的框架能够从这个特性中受益。另外,在C++的源代码中,Modules也是被禁用的。

@import:

  • 说了这么多,module 到底怎么用呢?
    答:Apple在LLVM5.0(也就是Xcode5带的最新的编译器前端中)引入了一个新的编译符号@import,使用@符号将告诉编译器去使用Modules的引用形式,从而获取好处。

    @import LDPMChart; 
    

大部分情况下等价于
#import <LDPMChart/LDPMChart.h>。
但后者需要增加一条使用限制:在Build Settings中将Enable Modules(C and Objective-C)打开。
这样就可以保持旧的写法,避免把项目中的所有引用都进行手动修改。不过,后者的引用方式在语法检查时并不严格,在缺少modulemap头文件暴露支持时,可以编译通过但会有missing submodule的warning。如果方便还是建议使用新的引用方式@import 规范化引用。

  • @import 小特性
    • 使用@import之后,你不用在project settings那里添加framework,系统会自动帮你加载上了

三、小问题附录

#import "" vs #import <>

  • <>: 引用系统文件,它用于对系统自带的头文件的引用,编译器会在系统文件目录下去查找该文件。
  • "": 用户自定义的文件用双引号引用,编译器首先会在用户目录下查找,然后到安装目录中查。
  • 上面两种方式的引用实质是搜索路径的不同。但无论哪种方式,编译器会将相对路径与引用内容组合成头文件的绝对路径:搜索路径+相对路径

Header Search Path

  • (User) Header Search Path

    • Header Search Path指的是头文件的搜索路径。
    • User Header Search Paths指的是用户自定义的头文件的搜索路径
  • Always Search User Paths

    • 如果设置了Always Search User Paths为YES,编译器会优先搜索User Header Search Paths配置的路径,在这种情况下#include <string.h>,User Header Search Paths搜索目录下面的文件会覆盖系统的头文件。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容