iOS 靜態庫(.a, .framework) 動態庫(.framework, dylib)

weixin_34185560發表於2017-06-16

上面的文章回答了這幾個問題:

  • 什麼是庫?
    庫就是程式程式碼的集合, 將N個檔案組織起來, 是共享程式程式碼的一種方式

  • 庫的分類?

    • 開源庫: 原始碼是公開的, 可以看到每個實現檔案 .m 的實現, 例如 Github 上常用的開源庫 AFNetworking, SDWebImage 等.
    • 閉源庫: 不公開原始碼, 是經過編譯後的二進位制檔案, 看不到具體的實現. 閉源庫又分為: 靜態庫 和 動態庫
  • 靜態庫的存在形式?
    .a
    .framework

  • 動態庫的存在形式?
    .dylib
    .framework

  • 靜態庫和動態庫的區別?

    • .a 檔案肯定是靜態庫, .dylib 肯定是動態庫, .framework 可能是靜態庫也可能是動態庫
    • 靜態庫在連結時, 會被完整的賦值到可執行檔案中, 如果多個APP都使用了同一個靜態庫, 那麼每個APP都會拷貝一份, 缺點是浪費記憶體, 類似於定義一個基本變數, 使用該基本變數是新複製了一份資料, 而不是原來定義的
    • 動態庫不會複製,只有一份, 程式執行時動態載入到記憶體中, 系統只會載入一次, 多個程式公用一份, 節約了記憶體. 類似於使用變數的記憶體地址一樣. 使用的是同一個變數
      但是專案中如果使用了自己定義的動態庫, 蘋果是不允許上架的, 在 iOS8 後 蘋果開放了動態載入 .dylib 的介面, 用於掛載 .dylib 動態庫
  • 靜態庫的運用場景?

    • 保護自己的核心程式碼, 如訊飛語音摸索了好多年探索出的結果當然要儲存起來, 都公開了公司怎麼生存
    • 將MRC的專案打包成靜態庫, 可以在ARC下直接使用, 不用轉換, 如別人使用 MRC 寫的開源庫, 放到自己的ARC專案中, 需要對每個檔案加一個編譯引數 -fno-objc-arc 這樣相對來說很麻煩, 將整個工程打包成靜態庫直接放到專案中即可, 也不用對每個檔案新增編譯選項
  • 靜態庫的特點?
    .a + .h
    .a : 可以看做所有 .m 檔案加密後的一個二進位制檔案
    .h : 標頭檔案, 使用者暴露可用的介面 (方法)

  • 製作靜態庫的過程 .a

    1. new -> project -> Cocoa Touch Static Liabrary
    2. 編寫邏輯程式碼
    3. Build Phases -> Copy Files 新增要暴露的標頭檔案
    4. Build Setting -> Build Active Architecture only (只構建活躍構架) -> nO
    5. a. 所有模擬器除錯版本靜態庫: 選中模擬器 command + b
      b. 真機除錯版本靜態庫: 選中 generic iOS Device , Command + b
      c. 真機發布靜態庫: 選中 generic iOS Device , Edit scheme Run -> Build Configuration -> Release. command +b
    6. 工程資料夾 Produts 下的 .a 檔案就是編譯得到的靜態檔案
    7. 右鍵 show finder 檢視所有版本的靜態庫
      Debug-iphonesos 除錯 真機版本
      Debug-iphonesimulator 除錯 模擬器版本
      Release-iphoneos 釋出 真幾版本
      Release-iphonesimulator 釋出 模擬器版本
      8 . 如何引入靜態庫?
      直接把 對應靜態庫 .a 和 暴露的.h 檔案 拖入到 目標工程中即可
    8. 合併靜態庫?
      lipo -create 模擬器除錯.a 模擬器釋出.a 真機除錯.a 真機發布.a output 通用.a
    9. 靜態庫注意:
      自己的靜態庫給別人用, 一般都是給兩個釋出版本 (模擬器, 真機), 最好不要合併. 如果給了使用者合併版的, 使用者無法分解.

    關於 lipo 命令
    點選檢視lipo命令

關於構架:
構架是什麼?
CPU 構架 是 CPU 廠商給屬於同一系列的 CPU 產品定的一個規範, 主要目的是為了區分不同型別 CPU 的重要指示, 模擬器上的構架和真機上的構架不是一樣的, 模擬器和模擬器之間, 真機和真機之間的構架也是不同的, 如果靜態庫的構架和測試專案對應的模擬器或者真機上的構架不對應就會報錯 "Undefined symbols for architecture arm64/i386"

檢視靜態庫對應的構架: lipo -info Xxx.a 

靜態庫都支援哪些構架?
模擬器架構
    iPhone4s ~ 5 : i386
    iPhone5s ~ 7Plus : x86_64
真機架構
    3GS~4s : armv7
    5/5c : armv7s(armv7相容armv7s)
    5s ~ 6sPlus : arm64
  • 靜態庫的製造過程 .framework
    1. new -> project -> Cocoa Touch Framework
    2. Build Settings -> Mach-O Type -> Static Library (預設是 Dynamic Library)
    3. 編寫邏輯程式碼
    4. 公開標頭檔案 Build Phases -> Headers -> 把Project 中需要暴露的 .h 檔案拖到 Public 中
    5. 將要公開的所有標頭檔案 引入到 總的標頭檔案 (庫名.h) 中,
    6. Build Setting -> Build Active Architecture Only -> NO
    7. 同 靜態庫.a 製作的步驟 5
    8. 專案資料夾 Products 下 的 庫名.framework 右鍵 show finder
    9. 同 .a 靜態庫製作的步驟7 得到所有型別版本的framework
    10. 將 需要的framework 拖入到目標工程中, 呼叫靜態庫的方法

2.動態庫 .framework
步驟跟 靜態庫 .framework 類似, 下面是不同的地方
1. Mach-O type -> Dynamic Library
將生成的動態庫 .framework 拖入到目標工程之後
2. General -> Embedded Binaries 中 新增該.framework
3. Linked Frameworks and libraries 中 會預設新增該 .framework

swift framework 動態庫 (swift 不支援靜態庫)
1. File --> project --> Cocoa Touch Framework (選擇swift 語言)
建立你需要的 swift 檔案. 完成程式碼邏輯
2. Build Phases --> Headers Public 中新增所有用得到的swift 檔案
要注意: 所有要暴露出來的swift 類和方法 都必須用public 修飾
3. Build Settings -> Mach-O type 選擇 Dynamic library (swift 語言智慧選擇動態庫)
4. Build Active Architecture Only 設為 NO
5. command + b 編譯一遍程式碼, 如果沒有問題的話, 動態庫已經生成好了
6. 工程資料夾 Products資料夾中 有個.framework 檔案, 選中, 右鍵 show finder
7. 可以拿到 .framework 檔案
8. 把 framework 檔案拖入要用到的工程中
9. General --> Embedded Binaries 中加入剛剛拖進去的 framework
10. 當framework 拖入工程後 xcode 會自動給 swift型別的 framework 建立一個檔案 (庫名-swift.h)
11. 工程中 引入 檔案 庫名-swift.h 後, 就可以呼叫所有 framework中暴露出來的 swift 方法.
更多詳細的介紹
- Swift完整專案打包Framework,嵌入OC專案使用

問題: Swift is not supported for static libraries. 不支援打包靜態庫
解決思路: - Swift打包靜態庫方法
上面的解決思路沒看懂, xcode 編譯後的檔案是什麼, 那麼,怎麼把編譯後的檔案加入靜態庫呢?

.bundle
使用第三方庫時 有可能會有一個.bundle 檔案, .bundle 其實是一個物理資料夾, 裡面可以放圖片等資源. 因為.bundle是一個物理資料夾 所以當被拖入到專案中就不會和自己專案中的圖片重名

.a 和 .framework
使用.a 時 需要同時將.a 和 .h 檔案拖入到工程中, 使用 .framework時 直接將這個資料夾拖入進去即可, 因為 .framework 資料夾中已經包含了 .h 檔案
.a + .h + .bundle = .framework 所以使用framework 更方便

相關文章