记一次 OC 编译过程中遇到的接口重复定义的问题

本贴最后更新于 1519 天前,其中的信息可能已经时移俗易

背景

前一段时间,项目组里有个小伙伴在调试项目的时候发现了个问题:将一个 OC 类的.h 文件引入 swift 的 bridge-header 文件编译就会报错:duplicate interface definition for class 'XXX',我顺着这个被重复定义的 XXX 接口名称一路往下找过去,发现确实重复定义了一个同名接口。所幸的是同样的接口名称,里面的声明也是一样的,而且其中有一个没有实现部分,于是删掉那个没有实现的接口,项目也可以正常编译运行了。
但是问题还没有结束,为什么没有把包含"XXX"接口的头文件引入 bridge 文件里的时候一切编译都是正常的,而此时项目里是有两个同名的 interface 的,而编译器却没有把错误抛出来?而在引入了 bridge 文件后编译器却立马抛出错误,这是为什么呢?

查找

通过搜索,我发现此时 bridge 文件里还 import 了一个文件,他里面包含着另一个"XXX"接口。哦,原来把两个包含同名接口的头文件 import 在同一个文件里编译器就会报错。如果把它们分开 import 在不同的文件里,我试了一下,居然不报错,编译能够顺利通过。好的,那接下来就要探究一下 import 背后究竟做了些什么。

探究

众所周知,OC 当中#import 是#include 的改良版本,#import 不会引起交叉编译,而且#import 确定一个文件只被导入一次,这就保证你在递归包含中不会出问题。OK,既然#import 和#include 的区别在此,那就说明#import 和#include 一样,将被导入文件包含进目标文件里,就和你找到被导入的头文件,将被导入的头文件里的所有内容复制到目标文件开头的效果是一样的。
所以,到这里,大概明白了为什么在同一个文件里导入包含相同接口名的文件时编译器会抛出错误,因为这就和在同一个文件里定义两个同名接口一样,编译器在对文件进行词法分析和语法分析时会立马检测出来,并抛出异常。

总结

以上过程均发生在预编译和编译阶段,看来编译器在预编译和编译阶段并没有对所有文件做一个全局的类型比对,仅仅对单个文件当中的类型做了比对处理。

  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    85 引用 • 139 回帖
  • oc
    2 引用

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...