手把手教你高效快捷的建立Swift Framework

前言:

 本文是我在工做中開發 Framework 過程當中的對踩過的坑走過的彎路的總結,此教程 Swift 和 OC 都適用,文章末尾附可能遇到的問題以及解決方案,但願給各位開發小夥伴一點幫助。ios

 本文主要講了一下內容:git

  1. 動態庫和靜態庫的區別
  2. 如何建立 swift 版的 framework
  3. 如何調試 Framework,兩種方法
  4. 關於 Framework 的CPU架構 以及如何合成 framework 的架構讓其即支持真機又支持模擬器,兩種方法
  5. 在開發 framework 中可能遇到的坑以及解決方案

開始:

 在咱們開發中最離不開的就是 Framework 好比 UIKit.framework,因此對 framework 應該是比較熟悉的,那麼在開發中也常常把本身的所作模塊的代碼作成 framework,場景以下:github

  1. 方便給別人使用咱們本身的模塊
  2. 提供給第三方使用,且又不肯意別人看到本身的內部實現邏輯
  3. 模塊化提升代碼的複用性

動態庫和靜態庫的區別

靜態庫:

 連接時完整地拷貝至可執行文件中,被屢次使用就有多份冗餘拷貝。swift

動態庫:

 連接時不復制,程序運行時由系統動態加載到內存,供程序調用,系統只加載一次,多個程序共用,節省內存。數組

區別:

靜態庫和動態庫是相對編譯期和運行期的:靜態庫在程序編譯時會被連接到目標代碼中,程序運行時將再也不須要改靜態庫;而動態庫在程序編譯時並不會被連接到目標代碼中,只是在程序運行時才被載入,由於在程序運行期間還須要動態庫的存在。xcode

總結:

同一個靜態庫在不一樣程序中使用時,每個程序中都得導入一次,打包時也被打包進去,造成一個程序。而動態庫在不一樣程序中,打包時並無被打包進去,只在程序運行使用時,才連接載入(如系統的框架如UIKit、Foundation等),因此程序體積會小不少,可是蘋果不讓使用本身的動態庫,不然審覈就沒法經過。bash

下面就一步一步的演示如何製做一個 framework, 以及製做本身的 framework 中可能會遇到的坑,以及如何解決。做爲演示作個比較簡單的數組亂序的 framework架構

新建一個 framework

  1. File -> new -> Progect-> 選中 iOS -> Cocoa Touch Framework

1.png

  1. 點擊 Next -> Protect Name 爲 ArrayDisorderSDK launguage 選爲 Swift 點擊 Next 新建完成

2.png

  1. 在 Framework 中新建文件: 選 source 的時候 能夠選擇Cocoa Touch Class 或者Swift File 等 都是能夠的能夠根據本身的須要選擇

3.png

類名就取爲 ArrayDisorder,而後新建完成app

4.png

  1. 在ArrayDisorder 類中寫下數組亂序的代碼
open class ArrayDisorder: NSObject {
    
    open func disorder (orders:Array<Any>) -> Array<Any> {
        var temp = orders
        var count = Int(temp.count)
        while count > 0 {
            let index = Int(arc4random_uniform(UInt32(Int32(count))))
            let last =  Int(count-1)
            temp.swapAt(index, last)
            count -= 1
        }
        return temp
    }
}

複製代碼

注意:也許你會發現 在 class 前面或者在disorder方法前有 open 關鍵字,說到這裏先說下和這個地方和oc 製做 Framework 不一樣的地方框架

  • oc 製做 framework 會生成一個和 framework 名字同樣的類 只有.h 文件 內容以下
//! Project version number for ArrayDisorderSDK.
FOUNDATION_EXPORT double ArrayDisorderSDKVersionNumber;

//! Project version string for ArrayDisorderSDK.
FOUNDATION_EXPORT const unsigned char ArrayDisorderSDKVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <ArrayDisorderSDK/PublicHeader.h>
上面的這句註釋說的很清楚 若是你想讓別人外面找到你在 framework 中的類你必須像 <ArrayDisorderSDK/PublicHeader.h> 這種格式同樣把 你的類導入這文件中

複製代碼

最後一句

// In this header, you should import all the public headers of your framework using statements like #import <ArrayDisorderSDK/PublicHeader.h>

複製代碼

 說的很清楚若是你想讓別人外面找到你在 framework 中的類你必須像 <ArrayDisorderSDK/PublicHeader.h> 這種格式同樣把 你的類導入這文件中,在編譯成 SDK 以後生成的頭文件中就能夠看到你對外開放的類和方法

 建立 Swift framework也會生成一個這樣的文件可是 則不須要這樣導入頭文件。只須要在要暴露給使用者的類名和方法名前面寫上 Open 或者 Public 當編譯成 Framework 以後會生成 "你的 framework 的名字-Swift.h"的文件 在這個文件中你能夠看到類名前面 表有 Public 或者 Open 關鍵字的類.

何時用 Open 何時用 Public?

  1. Open 在做用域外是能夠被訪問,繼承 ,用 Open 關鍵字修飾的開放類成員在做用域以外是可訪問和可覆蓋的。

  2. Pubic 在做用域外是可訪問的,但在做用域以外沒有子類。公共類成員是可訪問的,但在做用域以外是不可覆蓋的。

配置你的 Framework

  1. 配置動態或者靜態庫

點擊 framework 的 target build settings - linking -> Mach-o Type -> Static Library 或者 Dynamic Library

  1. Development Target

在這個 Demo 中 設置爲支持 iOS 8

8.png

  1. 還要配置 運行編譯的成的 Build Configuration 爲 release 若是不是 release 則在 release 環境下運行會出錯

走到這一步,基本 Framework 已經初步完成, Command + B

注意:編譯的時候 選擇的 Device 若是是模擬器 則生成的是 x86架構,僅支持模擬器,在真機上這個編譯的 Framework 則不能用 ,若是 Device 不選或者選擇你鏈接在電腦上的真機,則編譯成的是arm64 能夠在真機上跑可是不能用在模擬器,若是製做的 framework 須要在模擬器和真機上用,則須要把這兩個架構合成一塊,這個==待會下面詳細講.==

9.png

點擊生成的 Framework 而後 Show In Finder

10.png

如圖中所示,生成了ArrayDisorderSDK.framework 那麼這個文件就能夠直接給別人使用了.

調試 Framework

在咱們寫代碼時通常都習慣於邊寫邊調試,那麼在製做 Framework 時有兩種方法調試咱們的 Framework

第一種(不推薦)

新建一個名字是 testArrayDisorderDemo的 Progect 以下

11.png

直接把編譯好的 Framework 拖入到 testArrayDisorderDemo中

12.png

而後 import ArrayDisorderSDK

在 ViewDidLoad 中寫入以下代碼

let disOrder = ArrayDisorder() //Framework 中的封裝了亂序功能的類
        //disOrder.disorder(orders: [1,2,3,4,5,6,7,8,9]) 調用ArrayDisorder 對外公佈的類
        print(disOrder.disorder(orders: [1,2,3,4,5,6,7,8,9]))
        // 輸出:[8, 6, 2, 5, 3, 4, 7, 9, 1]

複製代碼

到此,咱們簡單的 framework 就能夠算完成了.

可是這中調試framework 的方法效率比較低,咱們每一次調試都須要從新把原來的 framework 從testArrayDisorderDemo中刪除而後從新導入.這樣比較麻煩.那麼下面有一種比較方便高效的方法。

第二種 建立一個依賴工程(推薦)

仍是testArrayDisorderDemo 這個測試 Framework 的工程

如圖所示

14.png

而後把ArrayDisorderSDK 拖入到testArrayDisorderDemo 文件中 如圖

15.png

而後打開testArrayDisorderDemo

-- > General ->Embedded Binaries-> 點擊加號-> add Other -> 選中ArrayDisorderSDK.xcodeproj

以下圖

16.png

)]

17.png

18.png

再選擇 Target 的地方你會發現 如今已經有連個 Taeget 一個是testArrayDisorderDemo 一個是ArrayDisorderSDK

若是選中 testArrayDisorderDemo就是運行 Demo 若是選中ArrayDisorderSDK 就是編譯 SDK

 這時你會發現能夠直接在testArrayDisorderDemo 的 ViewController 中直接 導入ArrayDisorderSDK就能夠了 不須要在刪除而後再拖入了. 最重要的是 ,當你選中的testArrayDisorderDemo Tagret 運行的時候 當程序走到 framework 中去的時候 你還能夠打斷點等方式調試. 效率會很高.

注意: 當你修改 framework 中的代碼時要想測試下修改的效果,你必需先編譯下你的 framework 的 target 如本文中所示的就要先編譯下ArrayDisorderSDK的 target,不編譯的話就至關於你的 測試你 framework 的 Demo 用的仍是原來的 framework 而不是修改後的

關於 Framework 的CPU架構

 CPU 的架構在不一樣的機型上有不一樣的 主要有一下:

arm7: 在最老的支持 iOS7的設備上使用

arm7s: 在 iPhone 5 和 iPhone 5c 上使用

arm64: 在 iPhone 5s 的64位 ARM 處理器上

i386: 在32位模擬器上使用

x86_64: 在64位模擬器上使用

固然一個 Framework 不須要所有支持,能夠根據須要.

 如上文所說, 編譯的時候 選擇的 Device 若是是模擬器 則生成的是 x86架構,僅支持模擬器,在真機上這個編譯的 Framework 則不能用 ,若是 Device 不選或者選擇你鏈接在電腦上的真機,則編譯成的是arm64 和 arm7 能夠在真機上跑可是不能用在模擬器,若是製做的 framework 須要在模擬器和真機上用,則須要把這兩個架構合成一塊,那麼這就須要合成架構了.

首先,咱們要了解,如何查看一個 framework 的架構

用命令: lipo -info

注意: -info 中 - 和 info 沒有空格,info 後面有一個空格

如圖所示

20.png

把ArrayDisorderSDK 文件拖入控制檯 而後回車 控制檯就能夠輸出ArrayDisorderSDK 的 CPU 架構 如 armv7 arm64

21.png

22.png

這個是支持真機的,若是支持模擬器則不行的,須要從新編譯:

 在上圖中也能看到 當選中ArrayDisorderSDK.framework show in Finder 時你會發如今上一層有四個文件夾(最多爲四個若是你只在 relesae 下真機上編譯 就只有一個文件夾) ,主要分爲 Debug 和 release 兩種環境下的 真機和模擬器 Debug-iphoneos/ Debug-iphonesimulator Debug 下的模擬器 Release-iphoneos/Release-iphonesimulator relesase 下的真機和模擬器

那麼咱們須要作的就是把Release-iphoneos/Release-iphonesimulator 下的兩種架構合成一個

架構合併:

第一種方法(不推薦)

用命令: lipo -create aa bb -output cc 加入你framework 的名字是 ArrayDisorderSDK

aa: 表示Release-iphoneos 文件夾下的 ArrayDisorderSDK.framework/ArrayDisorderSDK 的路徑 bb : Release-iphonesimulator 文件夾下的 ArrayDisorderSDK.framework/ArrayDisorderSDK

cc: 生成的文件名 是和你的 framework 同名的,好比叫ArrayDisorderSDK

生成的output 出來的ArrayDisorderSDK是須要把Release-iphoneos 文件夾下的 ArrayDisorderSDK.framework 的中的ArrayDisorderSDK 替換掉的.

注意:-create 以及-output 在 create 和 output前面以- 是沒有空格,可是在create 和 output後面是有一個空格的

上面說的可能不太好懂,那麼下面演示一下,化繁爲簡: 如圖

23.png

總之這種方法仍是太麻煩的,容易出錯,下面介紹另一種比較簡單的.

第二種:(推薦)

  1. 選中ArrayDisorderSDK.xcodeproj 新建一個名字爲UniversalArrayDisorder 的 target
    24.png

25.png
26.png

  1. 選中 UniversalArrayDisorder --> Build Phases --> 選中加號 --> 選中 New Run Script Phase
    27.png

28.png

而後在 腳本地址

下載一個名爲universal-framework.sh 文件 把文件內容拷貝到如圖所示

29.png

注意:universal-framework.sh 中 ${PROJECT_NAME} 要把這個換成你本身的 framework 的名字

設置完成以後 ,編譯UniversalArrayDisorder target 編譯成功以後,會自動打開一個生成 Framework 的文件夾,而後再查看架構信息你會發現,即支持真機也支持模擬器啦.

你可能會遇到的坑

1 找不到 framework

錯誤提示:

No such module xxx
複製代碼

解決:

緣由就是 Framework Search Path 中的路徑錯了 能夠參考 參考地址 解決方案手動設置 這個路徑是你向引用你的 framework 的項目拖自定義的 framework 時自動生成的 因此簡單的解決方案就是 刪除 framework 從新拖入 注意:拖的時候必定要確保 framework 和目標項目在同一個文件夾下,這樣就不會出問題了

2 找不到類

錯誤提示:

'xxxx' is unavailable: cannot find Swift declaration for this class
 xxxx 表示 framework 中的類名
複製代碼

解決:

framework 的架構錯誤: 若是如你的 framework 須要在模擬器上跑 那麼你的 framework 必須包含x86 若是還須要在真機上跑 那麼必須包含arm64 架構 能夠用命令檢查架構 lipo -info 參考

3 動態庫和靜態庫的問題

錯誤提示:

Reason: image not found
 Message from debugger: Terminated due to signal 6
複製代碼

解決:

動態庫 Embedded Binaries沒有 添加 your framework name.framework -> 添加 若是是靜態庫 則不須要添加 如圖

32.png

寫在最後:

參考文獻:

  1. :https://medium.com/flawless-app-stories/getting-started-with-reusable-frameworks-for-ios-development-f00d74827d11

  2. :https://medium.com/captain-ios-experts/develop-a-swift-framework-1c7fdda27bf1

  3. :https://www.raywenderlich.com/65964/create-a-framework-for-ios

 本文是在我開發中遇到的問題的一個總結,整體傾向與如何更方便高效的建立本身的 framework,對於 OC 和 Swift 建立 framework 的異同介紹較少,因爲本文重點不在於此,有機會下次再總結. 因爲工做繁忙,水平有限,不免有不全,或者說的不合適的地方,還請看到此文章的朋友不吝賜教.或者你對本文中有不理解的地方,都但願在評論區交流. 若是此文解決了你的問題,還請點贊支持下。

Demo地址 歡迎轉載,轉載請註明出處:https://juejin.im/post/5a5269a3f265da3e347b15de

相關文章
相關標籤/搜索