問題:項目中今天引入第三方庫報錯,報錯如下圖:
解決辦法:錯誤顯示是duplicate symbol,于是前往項目Build Settings
-> Other Linker Flags
中刪除掉之前添加的 -all_load
,項目恢復正常。
Xcode中Other Linker Flags的作用:
- 在iOS開發中,引入第三方的一些靜態庫,導入后第三方庫就會出現類似的問題,一般的第三方庫的開發文檔中都會寫出這種問題的解決辦法,如在
Other Linker Flags
中加入-Objc
或者-all_load
或者-force_load
這樣的解決方法,為什么要這么做呢?首先引入一個連接器的概念。
鏈接器:
又譯為鏈接器、連接器,是一個程序,將一個或多個由編譯器或匯編器生成的目標文件外加庫鏈接為一個可執行文件,如C代碼到可執行文件經歷的步驟是:
源代碼 -> 預處理器 -> 編譯器 -> 匯編器 -> 機器碼 ->鏈接器 -> 可執行文件
在最后一步需要把 .o
文件和 C
語言運行庫鏈接起來,這時候需要用到 ld
命令。源文件經過一系列處理以后,會生成對應的 .obj
文件,然后一個項目必然會有許多 .obj
文件,并且這些文件之間會有各種聯系。鏈接器就是把這些目標文件和所用的一些庫鏈接在一起形成一個完整的可執行文件。
那么,Other Linker Flags
設置的值實際上就是 ld
命令執行時后面所加的參數。
蘋果官方的一段話:
The “selector not recognized” runtime exception occurs due to an issue between the implementation of standard UNIX static libraries, the linker and the dynamic nature of Objective-C. Objective-C does not define linker symbols for each function (or method, in Objective-C) - instead, linker symbols are only generated for each class. If you extend a pre-existing class with categories, the linker does not know to associate the object code of the core class implementation and the category implementation. This prevents objects created in the resulting application from responding to a selector that is defined in the category.
那么,Other Linker Flags
設置的值實際上就是 ld
命令執行時后面所加的參數
-Objc
:一般這個參數足夠解決前面提到的問題,這個flag告訴鏈接器把庫中定義的Objective-C類和Category都加載進來。這樣編譯之后的app會變大,因為加載了很多不必要的文件而導致可執行文件變大。但是如果靜態庫中有類和category的話只有加入這個flag才行,但是Objc也不是萬能的,當靜態庫中只有分類而沒有類的時候,Objc就失效了,這就需要使用-all_load或者-force_load了。-all_load
: 會強制鏈接器把目標文件都加載進來,即使沒有objc代碼。但是這個參數也有一個弊端,那就是你使用了不止一個靜態庫文件,那么你很有可能會遇到ld: duplicate symbol錯誤,因為不同的庫文件里面可能會有相同的目標文件 這里會有兩種方法解決 1:用命令行就行拆包. 2:就是用下面的這個參數-force_load
:所做的事情跟-all_load其實是一樣的,只是-force_load需要指定要進行全部加載的庫文件的路徑,這樣的話,你就只是完全加載了一個庫文件,不影響其余庫文件的按需加載 .