iOS开发总结-Xcode常见错误
coldrush
8年前
<p>这篇文章中收录了Xcode出现的各种错误,并对错误给出了正确的解决方案,以便帮助遇到困难的朋友。</p> <p>文章由作者刘小壮维护并持续更新,有新的问题并且文章中没有收录的,可以在下面评论区中提出,我会收录在文章中供大家参考。如果有问题不能解决的,也可以在下方评论区中提出,我会尽力帮助解决,并且将解决方案添加到文章中供其他人参考。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/32f4fd2050b4d69724c6bf600eb51622.jpg"></p> <p>占位图</p> <pre> <code class="language-objectivec">"file/file.h" file not found</code></pre> <p>如果遇到这种类型的问题报错,可以分为三部来解决,由简到复杂一步一步来,直到解决问题位置。</p> <p>1. 点击Xcode -> Project -> Clean清除缓存或者使用⌘ + ⇧ + k快捷键来清除。<br> 2. 点击Xcode -> Window -> Projects 清除Derived Data的缓存,在清除缓存之前先彻底退出Xcode,然后直接删除缓存文件夹。<br> 3. 再Build Settings -> Header Search Paths 添加路径,$(SRCROOT)/项目名称/文件路径。</p> <p>如果上面这三种方法都没有解决问题,就要考虑一下文件是否存在或者导入方式是否有错误了。例如: # include<> 和 # include"" 、 # import<> 和 # import"" 的导入方式是否有错误。</p> <pre> <code class="language-objectivec">ld: -pie can only be used when targeting iOS 4.2 or later clang: error: linker command failed with exit code 1 (use -v to see invocation)</code></pre> <p>首先注意: -pie can only be used when targeting iOS 4.2 or later -pie 只能在ios4.2或更高版本上使用,所以你可以更改工程 Deployment Info —> Depoyment Target</p> <p>如果你的IDE报了如下错误:</p> <pre> <code class="language-objectivec">auto property synthesis is synthesizing property not explicitly synthesized</code></pre> <p>解决方法:</p> <p>project -> build settings -> Apple LLVM 6.0 - Warnings - Objective C -> Implicit Synthesized Properties -> NO.</p> <p>这样就会消除所有的 property 警告了。</p> <pre> <code class="language-objectivec">the file “XXX” could not be opened because you don't have permission to view it</code></pre> <p>今天使用Xcode6,突然提示我 "the file “XXX” could not be opened because you don't have permission to view it" 说我没有权限。</p> <p>可以在 Build settings->Product Name 项修改 .Product Name 项默认是 $(TARGET_NAME) ,可以修改任意app名称:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/3d76ad9c07eee5d20a1cf59f7f06e176.png"></p> <p style="text-align:center"><img src="https://simg.open-open.com/show/cb3cac22ce46ca43e63733ac1caa8dae.png"></p> <p>如果遇到上面的情况,还有一种方式解决:</p> <p>Project —> Build Setting —> Build Options —> Compiler for C/C++/Objective-C 中 修改这一项,变成 Default Compiler(Apple LLVM 6.0)</p> <p>这种方法可以解决很多因为编译器引发的问题。</p> <p>有的时候会遇到这样类型的错误:</p> <pre> <code class="language-objectivec">property type ‘id <maintabbardelegate>’ is incompatible with type ‘id <uitabbardelegate>’ inherited from ‘uitabbar’</code></pre> <p><img src="https://simg.open-open.com/show/f7beadacf68b31e4660a13eeb549b490.png"></p> <p>UIKit 代理</p> <p><img src="https://simg.open-open.com/show/e7e9c4a8f3e5b78a12075b211ecc2a81.png"></p> <p>自己定义的代理</p> <p>这是因为自己的代理属性名和继承的父类代理属性名重名了,这种情况只需要把自己代理属性名更改就可以。</p> <p>但是这种方法还不是很好的解决方式,最好的解决方式是在定义代理的时候,继承自父类的代理。这样做的好处是,符合 Objective-C 中的继承的特性;而且外界使用当前类的代理的时候,可以通过遵守当前类的代理,达到将父类的代理也遵守,更加方便外界使用。而且苹果官方也是这样做的。</p> <p><img src="https://simg.open-open.com/show/c324deb7fe5961511f27cfbabdc747f1.png"></p> <p>在 storyboard 中,由 controller A 跳转到 controller B 的时候然后报错:</p> <pre> <code class="language-objectivec">Warning: Attempt to present *** on *** whose view is not in the window hierarchy!</code></pre> <p>大致分析一下,应该是这么回事情,在 controller a 的 viewDidLoad 里面直接跳转 controller b ,然后导致在显示 controller b 的时候也调用了 controller a 来显示,然后发现这个 window 的层次结构就错乱了。</p> <p>在 controller a 中跳转的时候,要在 viewDidLoad 以及 viewDidAppear 之后才能跳转,所以可以自己想办法延时跳转,而不是直接跳转。也可以将这个方法写在其他位置,根据自身情况而定。</p> <pre> <code class="language-objectivec">The document "ViewController.xib" could not be opened. Unrecognized file content.</code></pre> <p>很多情况都会造成这个错误,最常见的是因为 svn 或者 git 等版本控制工具进行代码 update 的时候造成的。我们解决完冲突之后将Xcode退出,删除缓存,然后在右边的列表里找到 Open AS -> Interface Builder XIB Documents 就可以了。</p> <p>这个问题应该算是Xcode的一个 bug ,跟我们并没有关系。</p> <pre> <code class="language-objectivec">import <framework/framework.h> file not found</code></pre> <p>我们导入一个新的 framework 之后报 file not found 错误,或者当前 framework 导致其他 framework 报 file not found 错误,这都是因为路径导致的错误,我们需要指定一下程序的路径。</p> <p>解决方法:在 Build Settings -> Framework Search Paths 添加路径, $(SRCROOT)/项目名称/文件路径/文件名.framework</p> <pre> <code class="language-objectivec">storyboardd references cannot be the destinations of relationship segues prior to ios 9.0</code></pre> <p>iOS9之后苹果添加了一个新特性-Storyboard References,这个特性如果报以上错误,是因为这个新特性只支持iOS9及以上版本,需要将Xcode编译最低版本设置为iOS9。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/9cf84335594133c8b7cf2bd1ce146de9.png"></p> <p>Deployment Target</p> <pre> <code class="language-objectivec">This application's application-identifier entitlement does not match that of the installed application. These values must match for an upgrade to be allowed.</code></pre> <p>设备上已经有一个和当前运行程序相同identifier程序,需要将设备上相同identifier的程序删除,或者修改当前运行程序的Identifier,然后在重新运行即可。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/885c384d6e1e1bf1abd0dc980b2dc97e.png"></p> <p>Identifier</p> <pre> <code class="language-objectivec">项目名 does not have an architecture that 设备名 can execute.</code></pre> <p>这个问题主要是因为项目设置的ARM指令集,比设备指令集高,也就是项目没有兼容低版本设备的指令集导致的。所以需要我们设置更低的指令集来兼容低版本设备,这个设备版本不是iOS系统版本,而是硬件的版本,例如iPhone5、iPhone6这样的设备。</p> <p><img src="https://simg.open-open.com/show/a6cb63ccf3e63120aa56930adfb72530.png"></p> <p>ARM指令集</p> <p>如果重新设置了设备指令集,还是不能正常运行程序,并且出现下面的错误:</p> <pre> <code class="language-objectivec">failed to send the handshake ack</code></pre> <p>如果从错误信息上来看,是一个握手符号发送失败,但是并不是这样的,也不是因为网的问题。这主要是因为我们出现上面ARM指令集错误之后导致的,需要我们手动还原系统设置。</p> <pre> <code class="language-objectivec">具体操作 : 通用 -> 还原 -> 还原所有设置 (这个操作越狱机慎重)</code></pre> <pre> <code class="language-objectivec">Variables View (控制台变量) 不显示变量的值和内存地址,很多对象都显示为nil,而实际上是有值的。</code></pre> <p>这主要是因为我们将当前工程的 Edit Scheme 的 Build Configuration 设置为了 release 模式,在 release 模式下编译器会模拟真机运行状态,会对一些调试参数进行优化,包括不显示 Variables View 变量。</p> <p>所以解决方案就是我们将 Build Configuration 的 release 模式改为 debug 模式,变量值和内存地址就出来了。</p> <pre> <code class="language-objectivec">Unknown type name ‘ViewController’;did you mean ‘UIViewController’?</code></pre> <p>或</p> <pre> <code class="language-objectivec">Unknown type name ‘ViewController’;</code></pre> <p>这是因为在代码中的两个类,使用 #import 直接或间接的循环引用导致的,这个错误是发生在编译期的。例如 classA 中 #import 了 classB , classB 中 #import 了 classA ,或中间隔了几层的循环引用。</p> <p>解决方式是找到循环引用的类,然后在产生循环引用的任意一个类的 .h 文件中使用 @class 的方式引用,然后在类的 .m 中使用 #import 引用就可以解决。</p> <pre> <code class="language-objectivec">Could not find Developer Disk Image</code></pre> <p>问题所在:</p> <p>这种情况一般都是出现在真机调试的过程中,是因为测试设备系统版本比 Xcode 的可运行版本高,所以导致 Xcode 找不到对应的磁盘映射文件。</p> <p>解决方法1:</p> <p>对于这样的问题,我们可以通过升级 Xcode 来解决,只要把 Xcode 升级到最高版本这个问题就解决了。因为最新的 Xcode 可运行版本始终都是比最新的 iOS 系统高或持平,所以这种方法可以解决,而且这也是苹果希望的。</p> <p>但是升级 Xcode 的过程中会导致不能打开 Xcode ,严重影响我们的工作,而且 Xcode 体积比较大,升级过程对网速的要求比较高。而且下载一个 Xcode 之后也不一定立刻能用,有时候 Xcode 升级了,但是 <strong>Mac</strong> 操作系统版本不能支持 Xcode ,还要升级 <strong>Mac</strong> 操作系统,又是一天过去了。。。</p> <p>解决方法2:(个人推荐)</p> <p>对于这个问题,我们可以考虑添加 iOS 系统对应的 DeveloperDiskImage 文件解决,这也就是上面我们说的 Xcode 磁盘映射文件,下载并添加这个文件就可以了。</p> <p>具体文件可以直接 <strong>Google</strong> 下载一个,下载之后直接放在下面的目录即可。例如我现在要运行 iOS9.3.1 的系统,我就下载一个文件名为 9.3 (13E230) 的文件,然后放在这个目录,就可以正常运行真机了。</p> <p>/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/</p> <p>一个 DeveloperDiskImage 文件可以运行当前中等版本号的所有子版本号,例如这次更新的 9.3.1 系统的 DeveloperDiskImage 文件,就可以运行 9.3.0 — 9.3.9 的所有 9.3 开头的子版本号,对于其他系统版本同理。</p> <p>Xcode升级策略:</p> <p>对于 Xcode 的升级,我自己的想法是只有在 6.xx 和 7.xx 这样的大版本更新,我才会升级 Xcode ,其他小版本我都不会去升级。为了保证真机运行,每次更新 iOS 系统后,我都会采用上面的方式来升级 Xcode 磁盘映射文件,但 Xcode 我不会去升级。</p> <p>这主要还是因为 Xcode 体积比较大,升级一次确实不容易,而且频繁升级 Xcode 也没有什么大的变化。一般在 6.xx 和 7.xx 这样的大版本更新, Xcode 才会有比较大的变化,这时候我才会选择升级 Xcode 。</p> <pre> <code class="language-objectivec">iPhone6 is busy: Processing symbol files Xcode will continue when iPhone6 is finished</code></pre> <p style="text-align:center"><img src="https://simg.open-open.com/show/b9ab15ad0c91b771b82889a1f5de62f1.png"></p> <p>Processing symbol files</p> <p>真机运行时,经常会出现上面的错误,但是项目的配置、证书、设备什么的都没问题啊。</p> <p>其实从 Xcode 上面的进度信息也可以看到, Xcode 正在处理符号文件。 Xcode 每次连接新设备后,都会进行这步操作,只有第一次连接会这样,之后就不会了。所以我们要做的就是,等。。。</p> <pre> <code class="language-objectivec">Charles无法抓包</code></pre> <p>在 <strong>Mac</strong> 上下载 Charles 后,直接就可以抓包,而手机上配置代理后也可以抓包。</p> <p>但是有的时候 Charles 会出现无法抓包的情况,重新卸载后再安装,还是无法抓包。</p> <p>遇到这样的情况,可以按照下面的步骤,检查一下是否是配置的问题。</p> <pre> <code class="language-objectivec">1. 查看Charles下面两个选项是否勾选,如果勾选将其取消。 Proxy -> Proxy Settings -> Enable transparent HTTP proxying Proxy -> SSL Proxying Settings -> ->SSL Proxying -> Enable SSL Proxying 2. 查看Charles下面选项是否勾选 Proxy -> Mac OS X Proxy 3. 如果用过Lantern或者其他F墙工具,需要检查下面选项是否勾选,很多F墙工具会配置下面选项。 系统偏好设置 -> 网络 -> 高级 -> 自动代理配置</code></pre> <p>我不能使用 Charles 就是因为第三种情况,我做的就是直接将其取消,测试了一下还可以照常F墙。</p> <pre> <code class="language-objectivec">ld: library not found for -lBeeHive clang: error: linker command failed with exit code 1 (use -v to see invocation)</code></pre> <p>解决方案</p> <p>这种问题一般都是缺少库文件所导致的,例如使用某个第三方库,但没有导入其文件,就会报这样的错。所以需要根据提示信息,找到缺失的库文件,并将其拖入工程中即可。</p> <p>如果使用了 CocoaPods ,那就是没有更新 podfile 文件所导致的,执行 pod 命令并重新打开工程即可。</p> <pre> <code class="language-objectivec">[!] The master repo requires CocoaPods 1.0.0 -(currently using 0.39.0) Update CocoaPods, or checkout the appropriate tag in the repo.</code></pre> <p>升级 Xcode 8 和 Mac10.12 之后,在 pod update 的时候发现报这个错误。</p> <p>按照错误提示来说是升级 CocoaPods ,尝试之后升级失败。后来以为是 gem 的问题,打印了一下 gem 的地址,也没什么问题。</p> <pre> <code class="language-objectivec">http://ruby.taobao.org/ https://ruby.taobao.org/</code></pre> <p>赶快 Google 查了一下是什么问题。后来查到在 Mac10.11 之后,系统会把 CocoaPods 移到 /usr/local/bin 路径下。所以又重新安装了一遍 CocoaPods ,并指定了路径,就可以了。</p> <pre> <code class="language-objectivec">sudo gem install -n /usr/local/bin cocoapods</code></pre> <p>之前一般都是通过不指定路径的方式安装的,所以会安装到 CocoaPods 默认路径下。</p> <pre> <code class="language-objectivec">sudo gem install cocoapods</code></pre> <p>如果重新安装 CocoaPods 之后,还是报下面的错误,那就需要改一下 Podfile 文件。</p> <pre> <code class="language-objectivec">[!] The dependency `ReactiveCocoa (= 2.0)` is not used in any concrete target.</code></pre> <p>给 Podfile 文件添加上 target ,再运行 pod update 就没问题了。</p> <pre> <code class="language-objectivec">target “Project” do pod 'ReactiveCocoa' , '2.0' end</code></pre> <p> </p> <p>来自:http://www.jianshu.com/p/997ae94510c8</p> <p> </p>