靜態庫部分代碼未被連接解決方案

問題1

靜態庫打包時,經常會碰到send undefined select to instance。這種問題嚐嚐出在使用catagory擴展的方法中。

分析問題是怎麼發生的:

因爲catagory是運行時纔回去檢索符號表去尋找方法IMP。而在編譯時,編譯器並沒有檢測到有關聯關係,因此在宿主APP在編譯鏈接時,將catagory誤認爲沒有用到的文件而沒有連接進二進制碼中去。

解決辦法如下:

1、將所有的catagory改寫爲Helper類,將catagory擴展的方法改爲類方法。

2、宿主APP在編譯時添加force load/all load 參數。

方法1是對SDK接入方友好的做法,不需要接入方做什麼額外的操作就可以使用,推薦使用。


問題2

打好的SDK包由兩個部分組成,

1、Framework包裹的.a文件和頭文件。

2、由圖片資源,nib資源等組成的Bundle文件。


在測試宿主APP的時候,出現如下 “Unknown class <MyClass> in Interface Builder file” 這樣的錯誤提示。

仔細檢查SDK的Bundle資源包中的xib文件,發現在xib中使用了某些自定義的class,但是在項目中並沒有直接調用該類(因爲某些場景中並不需要)。

分析問題是怎麼發生的:

nib加載class是在運行時發生的,而不是在編譯時決定。這使得linker在連接時將這個class當成沒有被調用的廢棄類而『自作聰明』的優化掉了。

而nib在運行時加載時,通過class的字串來反射加載相應的class時找不到對應的class,於是發出警告。

解決辦法如下:

知道問題是怎麼發生的,問題的解決思路就很清晰了。

在sdk中假裝使用一次該類。

舉個例子:

我們在MyClass中寫一個空方法

+(void)forceLoad{};

在其他類中寫一個永遠不會被調用的方法:

+(void)forceLoadClass{

[MyClass1 forceLoad];

[MyClass2 forceLoad];

[MyClass3 forceLoad];

}

Well done!通過這種方法可以強制linker在鏈接時鏈接這些之前被誤優化掉的類。

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