参考文章: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