解決ios靜態庫中的類別(category)在工程中不能使用

蘋果推薦解決:


解決方法爲:找到 target 的圖標,更改其 Other Linker Flags 爲: -all_load 或 -force_load
-force_load,後跟隨一個文件位置,可以更精確地加載所需文件。
 
簡單點說就是,Objective-C 的動態特性使得需要,爲鏈接器添加一個標籤(設置 Other Linker Flags 爲 -ObjC)來解決通過 Category 向類添加方法的問題。
但這個標籤 -ObjC 在 64 位 和 iOS 中有問題,需要使用 -all_load 或 -force_load

總結如下:
如果,第三庫中沒有 category,Other Linker Flags 無需設置
如果,第三方庫中有 category,需要設置爲 -ObjC
如果,某些 Xcode 版本中,出現問題,修改設置爲 -all_load


鏈接:

http://stackoverflow.com/questions/2567498/objective-c-categories-in-static-library

http://www.blogjava.net/lincode/archive/2012/04/23/376373.html

 http://developer.apple.com/library/mac/#qa/qa1490/_index.html


目前最好解決:

鏈接:http://www.dreamingwish.com/dream-2012/the-create-the-static-the-library-containing-the-category.html

一、異常的原因


在連接一個含有category的靜態庫的時候,往往會得到一個運行時exception “selector not recognized”。

這是由於 UNIX的靜態庫實現、linker和Objective-C的動態結構三者之間的問題引起的。

Objective-C並不爲每個函數定義linker symbol,它只爲每個class生成linker symbol。(objc的動態結構)

如果你爲一個已存在的class創建了category,那麼linker並不知道要將原始class實現和category實現聯繫起來。這就導致了最終程序中的對象沒法響應category中的方法。

要解決這個問題,只要在build靜態庫時,加上linker flag “-ObjC”即可(在64位osx上和iOS程序上,這樣做還不夠),這個flag告訴linker將每個定義了class或者category的對象文件都載入靜態庫。


二、iOS程序還需要做的

用xcode4.3創建lib時,-ObjC這個flag默認是有的(之前的版本不記得了,好像4.x版本的都會默認帶這個參數),但是最終程序還是會拋這個異常,這是因爲linker的bug,對於64位osx程序和iOS程序,這個bug導致只包含category而不包含class的文件沒法從靜態庫中加載。

所以,apple建議我們爲要最終程序的linker加上-all_load或者-force_load參數。

-all_load選項強制linker加載所有包中的所有對象文件,即使文件中沒有Objective-C代碼也加載。-force_load是從Xcode3.2開始有的,它使得linker獲取包加載的控制權,每個-force_load參數後面都必須跟上一個包的路徑,然後這個包的所有對象文件都會被加載。

懶人使用-all_load,勤快人使用-force_load。。。

但是這樣始終不好,因爲這兩個選項都可能導致不必要的代碼被加載。


三、更好地方法

Three20給出了一個宏:

#define TT_FIX_CATEGORY_BUG(name) @interfaceTT_FIX_CATEGORY_BUG_##name @end\@implementatio TT_FIX_CATEGORY_BUG_##name @end

爲每個只包含Category的文件的Category的前面加上這樣一個宏(定義一個空的class),此時不再需要-all_load或者-force_load,因爲不存在只包含Category的文件,linker的bug也就無從體現。

四、目前我用:-ObjC


參考鏈接:http://blog.sina.com.cn/s/blog_7a7e49fb0101fu8l.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章