iOS 構建動態庫


一、構建步驟

  1. 創建一個動態庫 MyDynamicFramework

    1

  2. 創建一個測試類

    2

  3. 在 MyDynamicFramework.h(默認生成,可統一暴露頭文件) 中 #import "Person.h"

    #import <UIKit/UIKit.h>
    //! Project version number for MyDynamicFramework.
    FOUNDATION_EXPORT double MyDynamicFrameworkVersionNumber;
    //! Project version string for MyDynamicFramework.
    FOUNDATION_EXPORT const unsigned char MyDynamicFrameworkVersionString[];
    // In this header, you should import all the public headers of your framework using statements like #import <MyDynamicFramework/PublicHeader.h>
    #import "Person.h"
  4. 點擊工程 -> Targets -> Build Phases -> Headers。

    動態庫中新建的文件會自動添加到 project 列表,MyDynamicFramework.h 文件是處於 Public 列表中。由於動態庫外部使用者需要調用 Person.h 中的方法,所以也需要將 Person.h 拖拽到 Public 列表。

    3

  5. 編譯動態庫

    選擇動態庫對應的 Scheme,選擇 Generic iOS Device 或真機編譯出對應真機的動態庫,Command + B 編譯。在 Xcode 工程中的 Products(這個目錄不是工程源文件目錄,而是編譯后生成對應的沙盒目錄)找到 MyDynamicFramework.framework 文件,右鍵 show in finder。

    4

  6. 利用 lipo -info 查看動態庫所支持的 CPU 指令集。

    5

    新建工程后所編譯出來的動態庫所支持的 CPU 指令集是 arm 7、arm64。

    需要注意:

    lipo -info [文件]
    

    后面跟的是文件路徑,而不是 .framework 路徑

  7. 指令集種類

    • armv7|armv7s|arm64 都是 ARM 處理器的指令集
    • i386|x86_64 是 iOS 模擬器的指令集

    理論上指令集是向下兼容的,比如連接設備為 arm64,那么是有可能編譯出的動態庫所支持的指令集為 armv7s 或者是 armv7。但是向下兼容並不是說一個 armv7s 的動態庫可以用在 arm64 架構的設備上,如果連接的設備是 arm64 的,而導入的動態庫是沒有支持 arm64,那么在編譯階段即會報錯。

  8. Xcode 指令集的編譯選項

    打開 Target -> Build Setting -> Architectures

    6

    • Architectures:指明選定 Target 要求被編譯生成的二進制包所支持的指令集
    • Build Active Architecture Only:指明是否只編譯當前連接設備所支持的指令集,如果為 YES,那么只編譯出連接設備所對應的指令集;如果為 NO,則編譯出所有其它有效的指令集(由 Architectures 和 Valid Architectures決定)
    • Valid Architectures:指明可能支持的指令集並非 Architectures 列表中指明的指令集都會被支持

    編譯產生的動態庫所支持的指令集將由上面三個編譯選項所影響,首先一個動態庫要成功編譯,則需要這三個編譯選項的交集不為空。

  9. 制作支持各機型的動態庫

    • Build Active Architecture Only 統一為 NO
    • Architectures 和 Valid Architectures 都設置為 armv7、armv7s、arm64、arm64e

    真機 Command + B 則生成支持 armv7、armv7s、arm64 的動態庫,模擬器運行,則生成支持 i386、x86_64 的動態庫。

  10. 合並模擬器和真機動態庫

    7

    使用 lipo -create -output 命令合動態庫,注意路徑是文件路徑,不是 .framework 的路徑。

  11. 使用腳本合並

    • 新建一個 target 腳本。

    8

    • 粘貼以下腳本內容到指定位置

    9

    if [ "${ACTION}" = "build" ]
    then
    INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.framework
    DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
    SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework
    if [ -d "${INSTALL_DIR}" ]
    then
    rm -rf "${INSTALL_DIR}"
    fi
    mkdir -p "${INSTALL_DIR}"
    cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
    #ditto "${DEVICE_DIR}/Headers" "${INSTALL_DIR}/Headers"
    # 使用lipo命令將其合並成一個通用framework
    # 最后將生成的通用framework放置在工程根目錄下新建的Products目錄下
    lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"
    #open "${DEVICE_DIR}"
    #open "${SRCROOT}/Products"
    fi
    • 編譯新 target
    • 編譯完成后生成的 framework 位於工程源代碼根目錄下的 Products 文件夾下面,通過 lipo -info 可以看到動態庫已經支持 i386、x86_64、armv7、armv7s、arm64。

    注意:是工程目錄,不是沙盒目錄。

    10

    11

  12. 使用動態庫

    在新工程的 target -> General -> Embedded Binaries 中添加 MyDynamicFramework.framework。

    12

二、動態使用

2.1 使用別人提供的動態庫遇到的坑

①、第三方庫所支持的 CPU 指令集不全。
②、運行過程中出現 image not found 異常或者控制台沒有異常輸出。
原因:沒有往 Embedded Binaries 中添加 xxx.framework

2.2 動態庫動態更新問題

能否用動態庫來動態更新 AppStore 上的版本呢?

framework 本來是蘋果專屬的內部提供的動態庫文件格式,但是自從 2014 年 WWDC 之后,開發者也可以自定義創建framework 實現動態更新(繞過 apple store 審核,從服務器發布更新版本)的功能,這與蘋果限定的上架的 app 必須經過apple store 的審核制度是沖突的,所以含有自定義的 framework 的 app 是無法在商店上架的,但是如果開發的是企業內部應用,就可以考慮嘗試使用動態更新技術來將多個獨立的 app 或者功能模塊集成在一個 app 上面。

企業內部使用的 app,將企業官網中的板塊開發成 4 個獨立的 app,然后將其改造為 framework 文件最終集成在一款平台級的 app 當中進行使用,這樣就可以在一款 app 上面使用原本 4 個 app 的全部功能。

使用自定義的動態庫的方式來動態更新只能用在 in house(企業發布)和 develop 模式卻但不能在使用到 AppStore,因為在上傳打包的時候,蘋果會對我們的代碼進行一次 Code Singing,包括 app 可執行文件和所有 Embedded 的動態庫。因此,只要你修改了某個動態庫的代碼,並重新簽名,那么 MD5 的哈希值就會不一樣,在加載動態庫的時候,蘋果會檢驗這個 hash 值,當蘋果監測到這個動態庫非法時,就會造成 Crash。

2.3 iOS 如何使用 framework 來進行動態更新?

重要參考文檔:iOS 利用 Framework 進行動態更新

2.4 談談 Mach-O

  • 在制作 framework 的時候需要選擇這個 Mach-O Type,確定 static、dynamic 類型庫.
  • 為 Mach Object 文件格式的縮寫,它是一種用於可執行文件,目標代碼、動態庫、內核轉儲的文件格式。作為 a.out 格式的替代,Mach-O 提供了更強的擴展性,並提升了符號表中信息的訪問速度。

2.5 自己創建的動態庫

自建的動態庫和系統的動態庫有什么區別呢?

我們創建的動態庫是在自己應用的 .app 目錄里面,只能自己的 App Extension 和 APP 使用。而系統的動態庫是在系統目錄里面,所有的程序都能使用。

可執行文件和自己創建的動態庫位置:

一般我們得到的 iOS 程序包是 .ipa 文件。其實就是一個壓縮包,解壓縮 .ipa 后里面會有一個 payload 文件夾,文件夾里有一個 .app 文件,右鍵顯示包內容,然后找到一個一般體積最大的、與 .app 同名的文件,那個文件就是可執行文件。

20
21

在模擬器上運行的時候用 [[NSBundle mainBundle] bundlePath]; 就能得到 .app 的路徑。可執行文件就在 .app 里面。

而我們自己創建的動態庫就在 .app 目錄下的 Framework 文件夾里。

22

我們可以看一下可執行文件中對動態庫的鏈接地址。用MachOView查看可執行文件。其中 @rpth 這個路徑表示的位置可以查看Xcode 中的鏈接路徑問題,而現在表示的其實就是 .app 下的 Framework 文件夾。

23

24

下圖表示了靜態庫、自建的動態庫和系統動態庫:

25

三、文章

iOS 動態庫制作以及遇到的坑


免責聲明!

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



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