iOS 引入framework的常見問題和原理


今天在引入第三方framework時,我按照以前的方法,把framework加入到了下圖的地方:

默認是required的,之后程序就crash了,報錯dyld: Library not loaded,之后我把required 改成了optional,這次不crash了,但是運行時出錯,庫中的對象無法實例化,全部是空。

我是根據http://stackoverflow.com/questions/24333981/ios-app-with-framework-crashed-on-device-dyld-library-not-loaded-xcode-6-beta解決的,就是利用Embeded Binaries選項。 

 

先看看optional 和 required 有什么區別,如下是官方的說法:

Libraries and frameworks are designated as Required by default, but you can change this designation to Optional. Required libraries must be present on the host computer for the product to load. Optional libraries do not have to be present for the product to load. A Required framework will always be loaded into memory, but an Optional framework will be loaded only if needed. The initial load of the application will be faster if a large library that is never needed is designated as Optional.

 在看看framework的官方說明:

A framework is a hierarchical directory that encapsulates shared resources, such as a dynamic shared library, nib files, image files, localized strings, header files, and reference documentation in a single package. Multiple applications can use all of these resources simultaneously. The system loads them into memory as needed and shares the one copy of the resource among all applications whenever possible.

注意,根據上面的介紹,看起來framework中只能包含 dynamic shared library 2進制文件,其實不是,framework 中也可以包含靜態庫2進制文件!通過下面這個參數來指定:

這里如果指定為 Static Library(framework中包含的2進制文件就是個靜態庫),那么當這個framework就可以只加入Linked Frameworks and Libraries 選項卡中,系統會自動識別它的類型,並鏈接入目標文件。而如果指定為Dynamic Library(framework 中包含的2進制文件就是個動態庫) ,那么,加入到 Linked Frameworks and Libraries 選項卡中是不夠的,而是需要加入到Embeded Binaries選項卡中,加入后系統會自動為你在Linked Frameworks and Libraries選項卡里加入相同framework,打開對應的ipa,會看到 framework在單獨的一個文件夾中。我這里的理解是,Linked Frameworks and Libraries表示連接,動態連接也算連接,所以Embeded Binaries選項卡中中的項目也會出現在Linked Frameworks and Libraries選項卡中。

另外,如果framework中包含的2進制文件是個靜態庫,而我們把這個framework當成一個包含動態庫的framework,添加到了Embeded Binaries選項卡中,那么程序無法通過編譯,會報錯的。

如何看一個framework中的2進制文件是一個靜態庫還是一個動態庫呢?使用file 命令。

見下面的截圖,一個動態庫,一個靜態庫:

 

看到這里可以明白了,framework就是把以前的.a 和 .so 文件又包裝了一層目錄,加入了些其他必要的文件,比如以前用.a時需要單獨引入的一系列.h文件,這樣看起來更規范一些!

 

這里還有一篇好的博文 http://www.cnblogs.com/huizhang212/p/lipolib.html,說的是如何從.a除去不要的.o文件。

 

 

就是說,如果引入了第三方的動態庫,這個包含動態庫的framework就需要添加到 ipa包中,加載的時機看參數,如果是required,那么程序載入時就加載,如果是optional,那么是使用到時,才加載。如果引入了靜態庫,這個.a的鏈接也看參數?不都是需要把部分2進制代碼鏈接入目標文件嗎?有什么區別嗎?不太明白。我覺得當使用靜態庫時,這個required 和 optional就沒什么用了。

關於創建自定義framework,需要仔細研究一下這篇文章 http://www.cocoachina.com/ios/20141126/10322.html

 


 

又遇到了一個問題,用embeded 方式加入 lumberjack framework 后,運行時總出如下警告:

objc[2738]: Class DDTTYLogger is implemented in both /private/var/containers/Bundle/Application/621285FC-47C0-4631-A664-2764018435AD/Gamification.app/Frameworks/CocoaLumberjack.framework/CocoaLumberjack and /var/containers/Bundle/Application/621285FC-47C0-4631-A664-2764018435AD/Gamification.app/Gamification. One of the two will be used. Which one is undefined.

我搜索了工程源碼,沒有發現其他定義這個類的地方,之后,為了測試,我刪掉了 lumberjack framework ,直接加入了lumberjack.a 進行編譯,這次直接報錯了!這次錯誤就寫的很明白了,原來是工程引入的另一個.a中已經包括了lumberjack的源碼,我又沒有這個.a的源碼,所以在工程中就搜索不到另一個定義。

這也是解決這種類似問題的小技巧吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM