問題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在鏈接時鏈接這些之前被誤優化掉的類。