中心思想
這篇文章也是緊接著上一篇繼續(xù)歸納和總結(jié),在我們?nèi)粘5拈_發(fā)工作中,Xcode編譯器拋出的各種“無理取鬧”的異常和錯誤。
在每個異?;蝈e誤的下方,我會盡可能詳細地歸納解決辦法,解決方案中涉及網(wǎng)上取材的內(nèi)容,我會附上網(wǎng)址或者其他大神博客供大家參考。
如果文中有不當或者錯誤的地方,勞煩您指正,我會及時修改,以免誤導他人及一些iOS開發(fā)初學者。
Xcode編譯器頭疼腦熱的地方遠比我們知道的要多,如果您遇到過文中不曾提及的警告或者錯誤,并且知道如果解決它,請您以簡信或者Email的形式發(fā)送給我(網(wǎng)頁地址欄有我的郵箱地址),我會一并總結(jié)更新,我會附上您的信息(例如博客,Github地址)。在此先謝謝了。
1.Bitcode問題
XXX does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
上面這個問題也是iOS 9SDK發(fā)布以后出現(xiàn)在Xcode7中的新問題,Bitcode是Xcode7引入的新特性,旨在為App瘦身,網(wǎng)上對它通俗的解釋是在線版安卓ART模式。
下面這段話,是親身參與2015年WWDC大會的國內(nèi)一線開發(fā)者王巍的總結(jié):Bitcode 是 LLVM 的中間碼,在編譯器更新時,Apple 可以用你之前提交的 Bitcode 進行優(yōu)化,這樣你就不必在編譯器更新后再次提交你的 app,也能享受到編譯器改進所帶來的好處。Bitcode 支持在新項目中是默認開啟的,沒有特別理由的話,你也不需要將它特意關(guān)掉。
Apple Watch應用必須打開Bitcode,iOS沒有強制,但是Xcode7默認打開了Bitcode。
解決上述問題的方法:
1.更新library使包含Bitcode,否則會出現(xiàn)以上問題,陸續(xù)都會支持Bitcode。
2.關(guān)閉Bitcode,步驟如下。
找到工程的target->build settings->直接搜索bitcode->然后在搜索結(jié)果的Build Options選項下找到Enable Bitcode->將YES改為NO,如下動態(tài)圖所示。

2.升級Xcode7后上傳App時報錯

解決方案:進入TencentOpenApi_ios_Bundle.bunle 點擊顯示包內(nèi)容,把plist文件刪除即可
3.故事板與Masonry混合使用時報錯
原因:如果用的view是storyboard連線而來的,不是自己在代碼里創(chuàng)建的。 很可能運行的時候會報錯,說IB已經(jīng)定義的約束和Masonry的約束沖突。即使你拖進去控件后并沒有設置約束。
解決:按以前的方法先用故事版做好約束,然后在每個約束的屬性面板設置PlaceHolder : Remove at run time。 這樣在運行的時候會自動取消。
Masonry是一個Objective-C版本的第三方Autolayout庫,還有一個叫做snapKit的開源庫,它是Masonry的Swift版本。在Swift項目中,如果出現(xiàn)上述錯誤,解決辦法同上。
4.升級Xcode7后使用JSONKit第三方庫崩潰
出現(xiàn)問題的出處是: void *keyObjectISA = *((void **)keys[idx]);這一段。這個問題我也是從網(wǎng)絡搜集的,我沒用過JSONKit,一直都是用系統(tǒng)自帶的。但是下面的解決辦法在我朋友那里得到了驗證。如果您有異議,請您指正,我會及時修改。
解決辦法:將原項目中JSONKit.m文件替換成下面鏈接的實現(xiàn)文件即可
https://github.com/jcbertin/JSONKit
5.添加Scheme白名單
這個問題是引起一些在項目中使用到微信,支付寶或者微博SDK相關(guān)功能(支付,收藏,分享)出現(xiàn)錯誤的原因,它會導致Xcode報如下報錯:
canOpenURL:failedforURL:“weixin://app/wxdaae92a9cfe5d54c/” - error: “This app is not allowed to query for scheme weixin”
問題描述:在iOS 9下涉及到平臺客戶端跳轉(zhuǎn),系統(tǒng)會自動到項目info.plist下檢測是否設置平臺Scheme。對于需要配置的平臺,如果沒有配置,就無法正常跳轉(zhuǎn)平臺客戶端。因此要支持客戶端的分享和授權(quán)等,需要配置Scheme名單。
解決辦法如下:
1)在項目的info.plist中添加一LSApplicationQueriesSchemes,類型為Array。
2)然后給它添加一個需要支持的項目,類型為字符串類型;
下面是一些項目中常用的白名單,你有用到的你就添加到該數(shù)組下面,類型全部為string
mqqOpensdkSSoLogin
mqzone
sinaweibo
alipayauth
alipay
safepay
mqq
mqqapi
mqqopensdkapiV3
mqqopensdkapiV2
mqqapiwallet
mqqwpa
mqqbrowser
wtloginmqq2
weixin
6. directory not found for option

問題原因:Xcode7將framworks位置改變了
解決方法:
1)點擊項目,選擇 Targets->XXXTests
2)選擇build setting 選項,找到 Frameworks Search Path 或者 Library Search Paths
3)刪除$(SDKROOT)/Developer/Library/Frameworks,
或者使用$(PLATFORM_DIR)/Developer/Library/Frameworks替換
7.iOS 9舊狀態(tài)欄報錯
下圖是報錯的截圖

出錯原因:設置app的狀態(tài)欄樣式使用了舊的方式,在info.plist里面設置了View controller-based status bar appearance為NO,默認為YES,一般式iOS6的時候使用這種方式,iOS7,8也兼容,但是到了iOS9就報了警告。
解決辦法:
1)刪除原先編寫的代碼
[[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent]
2)然后在plist文件中添加項View controller-based status bar appearance,類型為Boolean,設置為YES(默認是NO),如下圖7-1所示。

3)然后在你自定義的導航控制器里面添加如下代碼
-(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; }
4)在模擬器上刪除應用程序并重新運行即可
8.大部分社交平臺接口不支持https協(xié)議。
這個問題也是上一篇中網(wǎng)絡請求出錯的一個分支。目前還有大量的應用是通過HTTP協(xié)議來訪問服務器的,而要讓所有的應用都轉(zhuǎn)向支持HTTPS,顯然是一件耗時的工作。所以下面的方法可以一試,但只是暫時性的。畢竟蘋果幫之前提出了App Transport Security(ATS)的概念,它的提出意味著蘋果將準備棄用HTTP,轉(zhuǎn)而支持HTTPS。
上述問題的解決方案就是設置域,可以簡單理解成,把不支持https協(xié)議的接口設置成http的接口。
具體方法:
1)、在項目的info.plist中添加一個Key:NSAppTransportSecurity,類型為字典類型。
2)、然后給它添加一個NSExceptionDomains,類型為字典類型;
3)、把需要的支持的域添加給NSExceptionDomains。其中域作為Key,類型為字典類型。
4)、每個域下面需要設置3個屬性:NSIncludesSubdomains、NSExceptionRequiresForwardSecrecy、NSExceptionAllowsInsecureHTTPLoads。均為Boolean類型,值分別為YES、NO、YES。
以下文章能夠幫助你更好的理解ATS的概念
如何使用ATS提高應用的安全性
ATS問題
App Transport Security dictionary primary keys

9.找不到.dylib文件,換成.tbd文件而又無法運行,請嘗試下面的方式來解決。
拿添加libsqlite3.dylib為例(你可別照本宣科)
1)在項目Target中的Link Binary With Libraries 手動添加,
首先點擊 “+” ;
2)顯示搜索添加頁面,在這里如果搜索之前的libsqlite3.dylib是搜不出來ios9之前的。所以需要點擊 Add Other,出現(xiàn)文件目錄頁面,正常情況這里也是找不到老的libsqlite3.dylib文件的,因為這個文件是隱藏掉的。所以需要按快捷鍵 CMD+Shift+G (Go to the folder),輸入/usr/lib后,進入隱藏的界面;
3)然后添加你需要的 *.dylib,如libsqlite3.dylib文件.大功告成
今天先告一段落,我會繼續(xù)更新,keep moving!給廣大無聊的程序員推薦一個小游戲,我最近無聊的時候在玩,叫做okay?(你要是在改Bug,當我沒說)。
另外給大家推薦一個bug收集工具,叫做Bugtags,我也是偶然在資深開發(fā)者唐巧的微信公眾號看見的,后來在自己的Demo中體驗了一下,感覺小巧實用,之后還接到了一個Bugtags開發(fā)團隊的使用情況回訪電話,就算幫助他們推廣一下。
更多有關(guān)Bugtags的內(nèi)容請參考以下鏈接:
Bugtags官網(wǎng)
Bugtags博客
更新兩個使用Swift語言出現(xiàn)的問題
1.新建playground報錯Unable to find execution service for selected run destination
這個問題參考一下就行了
解決步驟:
1.先關(guān)閉Xcode
2.cd到Xcode所在目錄,并打開終端輸入下面兩行命令
rm-rf~/Library/Developer/CoreSimulator/Devices
killall -9 com.apple.CoreSimulator.CoreSimulatorService
關(guān)于Playground
Playground,有人將它稱呼為“訓練場”,它可以讓Swift展示某些腳本語言的特性。實際上,Playground只是提供了一個可實時編譯運行并展示的交互式開發(fā)環(huán)境罷了,類似于著名的REPL。它的這項功能完全借助于LLVM編譯器強大的組織能力。
目前,Playground只支持Swift語言,但是一位歪果仁大神開發(fā)出了一個可以運行OC版本的Playground,有興趣可以去看看。點我嘍
2.dyld: Library not loaded:@rpath/libswiftCore.dylib
問題描述:真機測試時,出現(xiàn)上述錯誤
解決步驟:
1.在工程的Targets中找到Build Setting選項
2.搜索Embedded Content Contains Swift Code項,將其設置為YES
第三次更新
更新兩個問題,也是在網(wǎng)上搜集的,解決辦法比較詳細
1. “Unknown class XXViewController in Interface Builder file.” 問題處理
在靜態(tài)庫中寫了一個XXViewController類,然后在主工程的xib中,將xib的類指定為XXViewController,程序運行時,報了上述錯誤:
其實這個問題與Interface Builder無關(guān),最直接的原因還是相關(guān)的symbol沒有從靜態(tài)庫中加載進來。這種問題的處理就是在Target的”Build Setting”–>“Other Link Flags”中加上”-all_load -ObjC”這兩個標識位,這樣就OK了。
2.關(guān)于Unbalanced calls to begin/end appearance transitions for …問題的處理
當某個業(yè)務有這么一個需求,進入一個列表后需要立馬又push一個web頁面,做一些活動的推廣。在iOS 8上,我們的實現(xiàn)是一切OK的;但到了iOS 7上,就發(fā)現(xiàn)這個web頁面push不出來了,同時控制臺給了一條警告消息,即如下:
Unbalanced calls to begin/end appearance transitions for ...
在這種情況下,點擊導航欄中的返回按鈕時,直接顯示一個黑屏。
我們到stackoverflow上查了一下,有這么一段提示:
occurs when you try and display a new viewcontroller before the current view controller is finished displaying.
意思是說在當前視圖控制器完成顯示之前,又試圖去顯示一個新的視圖控制器。
于是我們?nèi)ヅ挪榇a,果然發(fā)現(xiàn),在viewDidLoad里面去做了次網(wǎng)絡請求操作,且請求返回后就去push這個web活動推廣頁。此時,當前的視圖控制器可能并未顯示完成(即未完成push操作)。
Basically you are trying to push two view controllers onto the stack at almost the same time.
解釋如下:
當幾乎同時將兩個視圖控制器push到當前的導航控制器棧中時,或者同時pop兩個不同的視圖控制器,就會出現(xiàn)不確定的結(jié)果。所以我們應該確保同一時間,對同一個導航控制器棧只有一個操作,即便當前的視圖控制器正在動畫過程中,也不應該再去push或pop一個新的視圖控制器。
所以最后我們把web活動的數(shù)據(jù)請求放到了viewDidAppear里面,并做了些處理,這樣問題就解決了。
原文鏈接
第四次更新
1.手動performSegueWithIdentifier沒有生效的問題
這個問題是因為對視圖控制對象的生命周期概念沒有深刻理解,比如說當用戶打開應用,判斷用戶是否登陸,如果未登陸,就跳轉(zhuǎn)到登錄頁面這個情況。
如果你將判斷用戶是否登陸的語句放到了視圖的viewDidLoad中去,那么這個方法是不會生效的。因為在viewDidLoad中就啟動segue的話,依然會被后來填充的視圖覆蓋,要是在視圖加載完成后的viewDidAppear中啟動segue,就不會出現(xiàn)錯誤了。