1. 程式人生 > >iOS 靜態庫製作(Xcode9.0,Framework製作,Bundle製作

iOS 靜態庫製作(Xcode9.0,Framework製作,Bundle製作

基本知識:

1. 庫類別

  • 靜態庫(.a 和.framework)
  • 動態庫(.liby和.framework)

2.靜態庫和動態庫的區別

2.1靜態庫

  • 平時我們用的第三方SDK基本上都是靜態庫。
  • 靜態庫在專案編譯時完整地拷貝至可執行檔案中,被多次使用就有多份冗餘拷貝。
  • 靜態庫很大的一個優點是減少耦合性,因為靜態庫中是不可以包含其他靜態庫的,使用的時候要另外匯入它的依賴庫,最大限度的保證了每一個靜態庫都是獨立的,不會重複引用。
  • 靜態庫有.a 和 .framework兩種形式。

2.2動態庫

  • iOS平時使用的系統庫基本是動態庫,比如使用頻率最高的UIKit.framework和Fundation.framework。
  • 動態庫在程式執行時由系統動態載入到記憶體,供程式呼叫,系統只加載一次,多個程式共用,節省記憶體。
  • 動態庫在製作的時候可以直接包含靜態庫,也能自動link所需要的依賴庫。
  • 動態庫有.dylib/.tbd 、.framework兩種形式。
  • 蘋果禁止iOS開發中使用動態庫

3.版本

  • 真機-Debug版本
  • 真機-Release版本
  • 模擬器-Debug版本
  • 模擬器-Release版本

3.1 Debug

  • 含完整的符號資訊,以方便除錯
  • 不會對程式碼進行優化

3.2 Release

  • 不會包含完整的符號資訊
  • 的執行程式碼是進行過優化的
  • 的大小會比Debug版本的略小
  • 在執行速度方面,Release版本會更快些(但不意味著會有顯著的提升)

基本操作:.a靜態庫製作

1. 新建靜態庫工程

Create a New Xcode project -> Framework&Library -> Cocoa Touch Static Library 
這裡寫圖片描述

檔案結構如下:


2. 配置工程環境

2.1配置最低支援版本


2.2設定適配所有模擬器架構重要

project -> buildSeting -> Build Active Architecture Only 設為NO


3. 新建公開的檔案

3.1新建一個名為“testTool 檔案” 公開一個方法“testLog”



3.2新增公開檔案

3.2.1 點選“+” 新增”Header Phase”

3.2.2 新增檔案到 project

3.2.3 拖拽.h到 public

最終結果如下:


4. 生成.a檔案

此處注意需要生成4個

4.1修改環境


這裡可以選擇 Debug 和 Release 環境

這裡寫圖片描述

4.2選擇模擬器+Debug 環境+“cmd+R”生成.a


此處注意需要生成4個 
如此類推打出四種.a

  • 真機-Debug版本
  • 真機-Release版本
  • 模擬器-Debug版本
  • 模擬器-Release版本 

最終生成結果 
這裡寫圖片描述

4.3合併 debug 兩個包和 release 兩個包

注意:這裡的合併指的是 1.debug 下真機+模擬器合併 2.release 下真機+模擬器合併 

4.3.1將4個.a檔案拷貝到單獨資料夾

這裡寫圖片描述

4.3.2 合併

開啟終端 
命令規則

  • 1
  • 2
  • 3
  • 4

這裡寫圖片描述

標註出是自己起名

同理 release 也是如此 最後生成兩個檔案

這裡寫圖片描述

5.使用方法

5.1新建一個新工程 
**5.2引入檔案 
5.2.1引入libStaticWork-Debug.a和libStaticWork-Release.a

5.2.2引入 include 檔案 
在之前的靜態庫檔案找到任意的生成檔案 引入 include 檔案

這裡寫圖片描述

最後引入結果如下

5.3呼叫以及結果

這裡寫圖片描述

基本操作:.framework靜態庫製作

1.新建 framework 工程

這裡寫圖片描述

2.新建檔案類

這裡寫圖片描述

3.修改工程檔案配置

build setting ->搜尋 mach -> 修改 mach -O Type ->static Library

這裡寫圖片描述

這裡寫圖片描述

4.引入其他第三方庫(如果有的話)

⚠️注意:匯入第三方靜態庫的時候不要選擇新增到target中

這裡寫圖片描述

5.暴露標頭檔案

拖拽檔案到這裡

這裡寫圖片描述

6.生成 .framework

6.1修改環境

這裡寫圖片描述

這裡可以選擇 Debug 和 Release 環境

這裡寫圖片描述

6.2選擇模擬器+Debug 環境+“cmd+R”生成.a

這裡寫圖片描述

此處注意需要生成4個 
如此類推打出四種.a

  • 真機-Debug版本
  • 真機-Release版本
  • 模擬器-Debug版本
  • 模擬器-Release版本 

最終生成結果

這裡寫圖片描述

7.合併 debug 兩個包和 release 兩個包

注意:這裡的合併指的是 1.debug 下真機+模擬器合併 2.release 下真機+模擬器合併 

7.1將4個.a檔案拷貝到單獨資料夾

這裡寫圖片描述

7.2 合併

開啟終端 
命令規則

  • 1
  • 2
  • 3
  • 4

這裡寫圖片描述

標註出是自己起名

同理 release 也是如此 最後生成兩個檔案

這裡寫圖片描述

**7.3替換檔案 
7.3.1尋找之前生成的 任意framework 
**7.3.2替換二進位制檔案

替換前

這裡寫圖片描述

替換後

這裡寫圖片描述

8.使用方法 
8.1新建工程 
8.2應用 framework 
8.3結果如下

這裡寫圖片描述

9.注意的地方

9.1警告 
如果我們什麼都不配置的話 應用 framework 裡面的檔案 會產生如下的警告 
missing submodule ‘StaticFramework.framewokrTool”

這裡寫圖片描述

解決方案: 
在 framework 的標頭檔案也就是建立 framework 時同名的.h裡面引入我們的標頭檔案

這裡寫圖片描述

就可以了

9.2資原始檔 .bundle

靜態庫中有使用到圖片、音視訊等資原始檔,可以將這些檔案打包成.bundle檔案供靜態庫使用。

最簡單的方法是,新建一個資料夾,將圖片、音視訊等資源拖到資料夾中,將資料夾字尾名改為.bundle. 
靜態庫想要使用裡面的資源的話需要先獲取到該.bundle檔案。

  • 1

靜態庫中使用.bundle檔案裡面的圖片的方法是:

  • 1
  • 2

⚠️注意:.bundle檔案無法封裝到framework裡,需要將.framework,.bundle同時匯入專案中才能正常使用

9.3使用category

在製作framework的時候,如果使用了category,則使用該framework的專案執行時會crash,此時需要在該工程中 other linker flags新增一個引數 -ObjC

這裡寫圖片描述

引數說明

  • ObjC:加了這個引數後,連結器就會把靜態庫中所有的Objective-C類和分類都載入到最後的可執行檔案中

  • all_load:會讓連結器把所有找到的目標檔案都載入到可執行檔案中,但是千萬不要隨便使用這個引數!假如你使用了不止一個靜態庫檔案,然後又使用了這個引數,那麼你很有可能會遇到ld: duplicate symbol錯誤,因為不同的庫檔案裡面可能會有相同的目標檔案,所以建議在遇到-ObjC失效的情況下使用-force_load引數。

  • force_load:所做的事情跟-all_load其實是一樣的,但是-force_load需要指定要進行全部載入的庫檔案的路徑,這樣的話,你就只是完全載入了一個庫檔案,不影響其餘庫檔案的按需載入

    1.什麼是庫?

    庫是程式程式碼的集合,是共享程式程式碼的一種方式

    2.根據原始碼的公開情況,庫可以分為2種類型

    a.開源庫

    公開原始碼,能看到具體實現 ,比如SDWebImage、AFNetworking

    b.閉源庫

    不公開原始碼,是經過編譯後的二進位制檔案,看不到具體實現。主要分為:靜態庫、動態庫

    3.靜態庫和動態庫的存在形式

    靜態庫:以.a 和 .framework為檔案字尾名。
    動態庫:以.tbd(之前叫.dylib) 和 .framework 為檔案字尾名。

    .a是純二進位制檔案,.a檔案不能單獨使用,至少要有.h檔案配合,而.framework除了二進位制檔案外,還包含一些資原始檔(標頭檔案,plist等),由於自身包含了標頭檔案,所以.framework可以單獨使用。

    .a和.framework兩種靜態庫,通常都是把需要用的到圖片或者xib檔案存放在一個bundle檔案中,而該bundle檔案的名字和.a或.framework的名字相同。

    ios 8 以後蘋果放開了動態庫。

    4.靜態庫和動態庫在使用上的區別

    靜態庫:連結時會被完整的複製到可執行檔案中,被多次使用就有多份拷貝。
    動態庫:連結時不復制,程式執行時由系統動態載入到記憶體,系統只加載一次,多個程式共用(如系統的UIKit.framework等),節省記憶體。

    5.建立靜態庫可能出於以下幾個理由:

    1.你想將工具類程式碼或者第三方外掛快捷的分享給其他人而無需拷貝大量檔案。

    2.你想讓一些通用程式碼處於自己的掌控之下,以便於修復和升級。

    3.你想將庫共享給其他人,但不想讓他們看到你的原始碼。

    4.比如很老的框架使用的是MRC環境下面的框架,那麼我們只需要將其打包成靜態庫就可以了,這樣就不用擔心是不是ARC環境了。

    6、iOS裝置架構

    模擬器:
    iPhone4s-iPnone5:i386
    iPhone5s-iPhone7 Plus:x86_64

    真機:
    iPhone3gs-iPhone4s:     armv7
    iPhone5-iPhone5c:        armv7s
    iPhone5s-iPhone7 Plus: arm64

    支援armv7的靜態庫可以在armv7s上正常執行。

    Xcode建立靜態庫詳解(Cocoa Touch Static Library)(本人使用的是Version 6.3)

    一、建立靜態庫檔案(.a 檔案)

    開啟Xcode, 選擇File ----> New ---> Project。 

    選擇iOS ----> Framework & Library ---> Cocoa Touch Static Library。

    點選Next。按照流程一步一步的建立工程。

     注意靜態庫檔案的版本(4種)

    1.真機-Debug版本

    2.真機-Release版本

    3.模擬器-Debug版本

    4.模擬器-Release版本

    就是在build configuration 裡面進行調整一下debug和release,然後分別在真機和模擬器上面進行編譯。

    結果如下圖:

     

    除錯版本(Debug版本) VS 釋出版本(Release版本)

    --------------------------------------------------------------------------------

    - 除錯版本會包含完整的符號資訊,以方便除錯

    - 除錯版本不會對程式碼進行優化

    - 釋出版本不會包含完整的符號資訊

    - 釋出版本的執行程式碼是進行過優化的

    - 釋出版本的大小會比除錯版本的略小

    - 在執行速度方面,除錯版本會更快些,但不意味著會有顯著的提升

     所以我們建議在產品即將上線的時候要進行如下圖的調整:

    二、應用靜態庫檔案(.a 檔案)

    1.想讓靜態庫檔案給別人使用,需要將標頭檔案暴露給別人。按著下面的步驟將標頭檔案新增進來。

    再點選libstatic.a右擊show In Finder 就可以檢視如下圖:

    2.然後將靜態庫拖進專案中。就能利用標頭檔案了

     

    3.因為無論是模擬器還是真機都有不同的架構。所以經常會出現如下找不到某個架構的錯誤

    為了解決各個機型的模擬器都能用可以有2種方法:

    1.合併各個靜態庫(在終端中執行如下操作)

    cd /Users/XQ/Library/Developer/Xcode/DerivedData/static-bdsgvzfqigaspiaeivnhmmygrhgj/Build/Products/Release-iphonesimulator5s 

    lipo -info libstatic.a 

    Architectures in the fat file: libstatic.a are: i386 x86_64 

    $ cd /Users/XQ/Library/Developer/Xcode/DerivedData/static-bdsgvzfqigaspiaeivnhmmygrhgj/Build/Products/Release-iphonesimulator6 

    $ lipo -info libstatic.a 

    Architectures in the fat file: libstatic.a are: i386 x86_64

     1》.我們可以cd到.a檔案所在資料夾的當前目錄

     2》.再執行 lipo -info 靜態庫.a檔案

    這樣就可以查詢該靜態庫支援的架構是什麼。

    回到.a檔案所在資料夾所在的資料夾目錄:cd ..

    $ cd ..

    $ pwd

    /Users/XQ/Library/Developer/Xcode/DerivedData/static-bdsgvzfqigaspiaeivnhmmygrhgj/Build/Products

    合併2個靜態庫

    cd ..

    pwd

    /Users/XQ/Library/Developer/Xcode/DerivedData/static-bdsgvzfqigaspiaeivnhmmygrhgj/Build/Products

    $ lipo -create Release-iphonesimulator5s/libstatic.a  Release-iphonesimulator6/libstatic.a -output lib.a

    fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: Release-iphonesimulator5s/libstatic.a and Release-iphonesimulator6/libstatic.a have the same architectures (i386) and can't be in the same fat output file

    由於2個靜態庫都含有相同的架構,所以出現錯誤,因為我們合併的是Release-iphonesimulator6和Release-iphonesimulator5s之間的版本,都是模擬器的。其實我們在製作靜態庫的時候,無論是在模擬器還是真機的時候,設定Build Active Architecture Only為no的話,一次打包,如果是模擬器就會適用所有機型的模擬器,如果是真機就會適用所有機型的真機。實際上我們通常合併的是模擬器和真機的靜態庫。模擬器和真機版本合併完後,我們姑且稱之為“合併版本”吧,那麼分別會有debug合併版本和release合併版本,通常我們會在上線前將debug合併版本換成relaese合併版本(當然release合併版本會支援模擬器和真機)。目前還沒找到release合併版本和debug合併版本合併的方法(估計有,但是不會是這麼簡單的合併)。

    合併模擬器和真機的靜態庫,步驟如下:

    合併前:

    cd /Users/XQ/Library/Developer/Xcode/DerivedData/static-bdsgvzfqigaspiaeivnhmmygrhgj/Build/Products/Debug-iphonesimulator 

    lipo -info libstatic.a 

    input file libstatic.a is not a fat file

    Non-fat file: libstatic.a is architecture: x86_64

    cd /Users/XQ/Library/Developer/Xcode/DerivedData/static-bdsgvzfqigaspiaeivnhmmygrhgj/Build/Products/Debug-iphoneos

    lipo -info