[iOS]报错 duplicate symbol _OBJC_CLASS_$_XXX

884 阅读3分钟

Part1:问题描述

  • 最近一直被这个错误烦,我自己的情况是这样的,公司项目用 git 管理,我不小心在 Pods 下的第三方框架里新建了一个文件(如下图所示),我们约定趁这个文件叫做 SB 文件。之后编译了一次,后来意识到文件位置错了,我就把文件移出来,再重新放到需要的位置上。然后重新编译,Bulid Success
    Pods.png
  • 晚上回家把项目运行到自己电脑上,就报错,报的是我删除的文件没有添加到编译,然后我去 Build Phases 里的 Compile Sources 中查看,我后来添加的文件确实没有参与编译,然后我就把报错的文件添加到 Compile Sources。然后重新编译,Bulid Success

Compile Sources.png

  • 第二天上班,把昨晚的项目拷贝到公司电脑,Command + R运行,就报了duplicate symbol _OBJC_CLASS_$_XXX 错误。然后我把 SB 文件从编译中去掉,然后重新编译,Bulid Success

  • 晚上回到家,一运行项目,又开始报 SB 文件没有参与编译,然后又添加编译,然后重新编译,Bulid Success。第三天来到公司,又报duplicate symbol _OBJC_CLASS_$_XXX 错误。然后我把 SB 文件从编译中去掉,然后重新编译,Bulid Success

  • ......

  • 问题大致可以描述成这样,在家里的电脑上我需要将这个文件添加到 Compile Sources,但是在公司电脑上,我必须把这个文件从 Compile Sources 中删除。所以每次在不同的电脑上运行前,我需要先把文件或者删或者添加完成。

  • 这个问题没解决之前,我一直这样干,你能想象我的心情吗?

Part2:错误分析

  • 这个错误要注意“duplicate(重复) symbol(标识)”,这个词的意思是出现“_ 标识 _”重复。

  • 这个标识可以是一个关键词,比如你在全局常量里定义了一个 kSpaceGobel 标示,然后在某一个文件里,又定义了一个常量也叫作 kSpaceGobel,这个时候编译就会报这个错误。

  • 还有就是,你 #import “xxx.h” 时,手疾眼快,直接把 “.m” 文件当成 “.h” 文件导入到某一类里。

  • 网上说的最多的也就是上面两种情况,这两种情况我都熟悉。显然,我的错误不是这两种当中的一种。

Part 3:问题解决

  • 如果你项目里的某个文件不参与编译,那么 Clang编译器 不会将这个文件加入编译,也就是说,你在这个文件里写代码,是没有语法提醒的。

  • 我的问题解决方法是,最后是我自己跑到_/Users/你的用户名/Library/Developer/Xcode/DerivedData_ 下把这个文件夹下的所有文件全部删除了。然后重新编译,Bulid Success

  • 关于 _DerivedData_ 这个文件夹,我去 Google 上找了一下,没看到有详细说明这个文件夹作用的文献。我说个自己个人的猜想,不一定准确,仅作为你的参考。

  • 我猜想:Xcode 会将第一次编译好的文件保存在这个文件夹里,以后你再次运行的时候,Xcode会监测你更改了哪些文件,再次编译的时候就只编译那些你更改了的文件,再与原先编译好的文件合成,就可以运行了,这样就能避免你每次按下 command + R 的时候都要从零开始编译,从而提高工作效率。这个猜想的来源是,你第一次运行一个大的项目时进度条会走的很慢,但是一旦你运行过一次,以后再次运行的时候就会很快。

  • 需要强调的是,这个文件是唯一的,也就是说,每台 Mac 上的这个文件都是不一样的。所以,如果你以后也碰到类似,在一台电脑上跑的好好的项目,拷贝到另外一台电脑上就报莫名其妙的错误,大抵你应该来这个文件夹下看看。

NewPan 的文章集合

下面这个链接是我所有文章的一个集合目录。这些文章凡是涉及实现的,每篇文章中都有 Github 地址,Github 上都有源码。

NewPan 的文章集合索引

如果你有问题,除了在文章最后留言,还可以在微博 @盼盼_HKbuy 上给我留言,以及访问我的 Github