2011-07-25 25 views
36

我正在開發iOS應用程序的插件。我將它編譯成一個.a文件,然後由主xcode項目使用。在靜態庫中鏈接objective-c類別

到目前爲止,我已經在這個庫中創建了一個UIDevice類的類。當我運行使用這個庫崩潰的主要項目由於無法識別的選擇

- [的UIDevice平臺]:無法識別的選擇發送到實例

平臺是我通過類別添加fuinctions之一。

所以我認爲它根本沒有鏈接這些函數,並將一個c函數添加到與UIDevice類別相同的文件,然後從我的代碼中調用它。

這次主項目運行良好...所以我想也許這是我做的其他事情,並刪除了C函數。但看到它再次墜毀,由於無法識別的選擇器..

我的問題: 爲什麼xcode忽略類別定義,除非我調用一個函數聲明在同一個文件?

是否有一個xcode設置我可以改變,使它包括UIDevice類別中的這些方法,無論我是否從該文件調用函數?

歡呼聲

+0

[靜態庫中的Objective-C類別]的可能重複(http://stackoverflow.com/questions/2567498/objective-c-categories-in-static-library) – TalkLittle

回答

71

退房Building Objective-C static libraries with categories

目的-C不爲每個功能定義接頭符號(或 方法,在Objective-C) - 代替,接頭符號僅產生 爲每班。如果擴展一個預先存在的類, 鏈接器不知道將核心 類實現的目標代碼與類別實現相關聯。這可以防止 在生成的應用程序中創建的對象響應類別中定義的 選擇器。

要解決此問題,針對靜態庫 的目標鏈接必須將-ObjC選項傳遞給鏈接器。此標誌會導致鏈接器 加載庫中定義Objective-C 類或類別的每個對象文件。雖然此選項通常會導致可執行文件較大(因爲將其他目標代碼加載到 應用程序中),但它可以成功創建有效的 Objective-C靜態庫,其中包含現有的 類中的類別。


重要:對於64位和iPhone OS的應用程序,有一個 連接錯誤,防止-ObjC加載從只包含類別和無類的靜態 庫的對象文件。解決方法 是使用-all_load或-force_load標誌。

來源:@albertamg(linking objective-c categories in a static library

+0

感謝您的快速響應! 我將鏈接器標誌添加到兩個項目,但仍然得到相同的錯誤。然而,應用程序的文件大小已經比應該大,所以在這種情況下調用虛擬函數是最好的解決方案。 – micken

+2

@micken重要:對於64位和iPhone OS應用程序,存在一個鏈接器錯誤,可阻止-ObjC從僅包含類別和類別的靜態庫中加載對象文件。解決方法是使用-all_load或-force_load標誌。 – albertamg

+0

這個錯誤至今還存在嗎? –

8

我有同樣的問題。在子項目中定義的類別中定義的方法導致無法識別的選擇器異常。 (事實上​​,這表現爲無法在Interface Builder中指定UILabel子類; XIB包含IB中顯示的類(UILabel或UIView,取決於我在那裏拖動的內容),而不是我輸入的類,看起來怪異的XCode錯誤)

爲我工作的解決方案是使用-force_load:

在左側面板中,選擇您的主項目(根項目)。在右側,您將看到PROJECTTARGETS。選擇TARGETS。 轉到「構建設置」(在上面的欄中) - 「鏈接」 - 「其他鏈接器標誌」,並假設您的子項目名爲XXXXX,在那裏添加 -force_load ${BUILT_PRODUCTS_DIR}/libXXXXX.a (該項目有兩個子項,Debug和Release,但是你點擊這個複合項目,這樣如果同時影響調試和發佈)。

請注意,-force_load適用於單個庫,並且您可能需要爲每個子項目庫指定一個單獨的-force_load。

+1

我在「-force_load」中收到「libtool:未知選項字符」f「的錯誤?有什麼想法? – docchang

+0

這是一個很好的答案,謝謝! – RaffAl

-1

我有這個問題,並花了近1小時解決它。感謝上帝!它已經完成了。定義的方法應該是靜態類型!