参考文章:iOS里的导入头文件
在项目二进制化的过程中,打包framework经常出现头文件报错,主要缘于项目组件化完成后,因为文件的移动导致头文件引用方式不对,特此总结下import原理
#import<> 和 #import””
#import<> 是从Build Setting–>Search Paths–>Header Search Paths路径去检索头文件(Always Search User Paths 已经被标记废弃)
#import" " 是从Build Setting–>Search Paths–>User Header Search Paths–>Header Search Paths路径去检索头文件
新建一个TestHeaderImport项目,Podfile:
更新过后
User Header Search Path为空,Header Search Path为

从上图可以看到此时<>引用是会有智能提示的,但引号引用没有智能提示,主要是因为Search Path的原因,但使用引号引用也不会报错,因为在编译时引号引用除了去查User Header Search Paths还会去寻找Header Search Paths
如果此时把Header Search Path清空,那么<>引用也不会有智能提示
如果此时把User Header Search Path设置为上面配置,那么引号引用会智能提示和<>引用并不会
疑点:即使User Header Search Path 和 Header Search Path都删除的话,仍然可以编译通过
$(inherited)代表继承,此处加上这个配置代表继承上级配置,xcode继承链:
Resolved <- Target <- xcconfig <- Project <- iOS Default

可以看到Target中如果配置了$(inherited)那么将从xcconfig、Project、iOS Default中同项配置继承过来
其中cocoapods会自动生成xcconfig文件
我们也可以自定义自己的xcconfig文件,创建好.xcconfig文件在下图选中即可

我们将cocoapods生成的xcconfig中search_path删除
发现仍然能编译通过,后来发现xcconfig中的OTHER_CFLAGS也配置了路径,将其删除后,发现此时编译报错了。
OTHER_CFLAGS中
-isystem dir
Search dir for header files, after all directories specified by -I but before the standard system directories. Mark it as a system directory, so that it gets the same special treatment as is applied to the standard system directories. If dir begins with =, then the = will be replaced by the sysroot prefix; see –sysroot and -isysroot.
用 -isystem 修饰的路径,会打上系统路径的标,所以此处设置也会生效。
我们平时使用的时候,在依赖自己模块的头文件时,使用引号引用,在依赖其他模块的头文件时,使用<>引用
首先在依赖自己模块的头文件时,使用引号引用,因为尖括号引用会直接报错,原因是尖括号引用不会搜索当前文件所在的路径

其次在依赖其他模块的头文件时,使用<>引用
cocoapods会将依赖的库放进HeaderSearchPath中- 在依赖二进制包时,单纯使用引号头文件会报错

因为在header search path中指定了头文件目录,单独引入头文件会找不到

上图中后面的non-recursive代表不递归查找指定路径,解决头文件报错可以使用以下几种方案:
- 可以将此项设置改为
recursive,但是这样会导致:cocoapods默认配置为non-recursive,会导致重复工作,所有此类依赖都需这样设置- 设为
recursive会降低编译效率 - 如果项目后期使用二进制依赖,会导致文件引用问题,除非自定义二进制打包脚本
- 使用路径/文件名的方式,其中使用引号和
<>都可以,但推荐使用<>,因为可以提高编译效率,具体原因上文已经解释12#import <UMMobClick/MobClick.h>#import "UMMobClick/MobClick.h"
在引入头文件时,发现下面写法也是可以的,原因参考非framework引用,类似原来是<A/A.h>,其中A.h 又被包了一层B,最终变为<A/B/A.h>
虽然上面引用不会报错,但不建议这样使用,因为当时在做项目二进制依赖时,这样使用会导致报错,因为后面一直未曾重现,留待再次遇见时探究原因。
还可以想到的一个原因便是,如上面引入的UMengAnalytics-NO-IDFA分为多个版本的二进制包,当在不同需求下依赖不同二进制是,代码里需要更改头文件引入
了解了import原理后,对目前打包二进制时报的头文件错误有一个清晰的认知,所以下一步要做的便是将库import方式做些更改,将依赖别的库的头文件引用方式改为<>引用,最终实现所有库的二进制化,大大提升开发编译效率
最后附上更改脚本:header_change