天天看點

關于Xcode上的Other linker flags

一、問題說明

之前下了一個第三方的靜态庫.a,然後在運作時一直提示

2015-06-14 15:38:33.135 BRTExample[5890:695264] -[CBUUID toString]: unrecognized selector sent to instance 0x1742281c0

2015-06-14 15:38:33.135 BRTExample[5890:695264] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CBUUID toString]: unrecognized selector sent to instance 0x1742281c0'

*** First throw call stack:

(0x1848942d8 0x1960680e4 0x18489b3a4 0x184898154 0x18479accc 0x100082d7c 0x18450319c 0x184500b3c 0x1844fc9d4 0x1000e8fd4 0x1000e8f94 0x1000f3db8 0x1000ec2c4 0x1000f65d4 0x1000f8248 0x19689922c 0x196898ef0)

libc++abi.dylib: terminating with uncaught exception of type NSException

二、問題解決

很有可能靜态庫中添加了CBUUID的category,是以

Targets選項-Build Settings-搜尋Other linker flags,輸入-all_load

三、拓展

摘自(http://blog.sina.com.cn/s/blog_4cd8dd130102v47r.html)

Targets選項下有Other linker flags的設定,用來填寫XCode的連結器參數,如:-ObjC -all_load -force_load等。

還記得我們在學習C程式的時候,從C代碼到可執行檔案經曆的步驟是:

源代碼 > 預處理器 > 編譯器 > 彙編器 > 機器碼 > 連結器 > 可執行檔案

在最後一步需要把.o檔案和C語言運作庫連結起來,這時候需要用到ld指令。源檔案經過一系列處理以後,會生成對應的.obj檔案,然後一個項目必然會有許多.obj檔案,并且這些檔案之間會有各種各樣的聯系,例如函數調用。連結器做的事就是把這些目标檔案和所用的一些庫連結在一起形成一個完整的可執行檔案。

如果要詳細研究連結器做了什麼,請看:http://www.dutor.net/index.php/2012/02/what-linkers-do/

那麼,Other linker flags設定的值實際上就是ld指令執行時後面所加的參數。

下面逐個介紹3個常用參數:

-ObjC:加了這個參數後,連結器就會把靜态庫中所有的Objective-C類和分類都加載到最後的可執行檔案中

-all_load:會讓連結器把所有找到的目标檔案都加載到可執行檔案中,但是千萬不要随便使用這個參數!假如你使用了不止一個靜态庫檔案,然後又使用了這個參數,那麼你很有可能會遇到ld: duplicate symbol錯誤,因為不同的庫檔案裡面可能會有相同的目标檔案,是以建議在遇到-ObjC失效的情況下使用-force_load參數。

-force_load:所做的事情跟-all_load其實是一樣的,但是-force_load需要指定要進行全部加載的庫檔案的路徑,這樣的話,你就隻是完全加載了一個庫檔案,不影響其餘庫檔案的按需加載

在添加完該庫後,需要在Xcode的Build Settings下Other Linker Flags裡面加入-ObjC标志,這個标志以前沒使用過,是以我就專門研究了一下它的作用。

 之是以使用該标志,和Objective-C的一個重要特性:類别(category)有關。根據這裡的解釋,Unix的标準靜态庫實作和Objective-C的動态特性之間有一些沖突:Objective-C沒有為每個函數(或者方法)定義連結符号,它隻為每個類建立連結符号。這樣當在一個靜态庫中使用類别來擴充已有類的時候,連結器不知道如何把類原有的方法和類别中的方法整合起來,就會導緻你調用類别中的方法時,出現"selector not recognized",也就是找不到方法定義的錯誤。為了解決這個問題,引入了-ObjC标志,它的作用就是将靜态庫中所有的和對象相關的檔案都加載進來。

繼續閱讀