iOS 靜態庫詳解與開發

FBY展菲發表於2019-03-04

一:介紹

1. 什麼是庫?

庫是共享程式程式碼的方式,一般分為靜態庫和動態庫。

靜態庫:連結時完整地拷貝至可執行檔案中,被多次使用就有多份冗餘拷貝。

動態庫:連結時不復制,程式執行時由系統動態載入到記憶體,供程式呼叫,系統只載入一次,多個程式共用,節省記憶體。

iOS 靜態庫詳解與開發

2. 兩種形式中.framework的區別

如上圖所示,靜態庫的形式包含.a和.framework兩種形式。

動態庫的形式包含.dylib和.framework,其中.framework包括私有的.framework和系統的.framework。

靜態庫和動態庫都有私有的.framework,但是根本上有所不同,動態庫私有的.framework,上架會有機審規則,並且不能動態下載。靜態庫私有的.framework,類似一個封裝的程式碼塊,沒有過多的限制。

3. 靜態庫中.a與.framework的區別

.a是一個純二進位制檔案,.framework中除了有二進位制檔案之外還有資原始檔。
.a檔案不能直接使用,至少還有.h檔案配合,.framework檔案可以直接使用,因為本身包含了h檔案和其他檔案

4. 靜態庫的優點

  • 實現程式的模組化,將固定的業務模組化成靜態庫。
  • 方便共享程式碼,即可以和別人分享你的程式碼庫,但別人又看不到你程式碼的實現。
  • 開發第三方sdk的需要,例如兩個公司之間業務交流,不可能把原始碼都傳送給另一個公司,這時候將私密內容打包成靜態庫,別人只能呼叫介面,而不能知道其中實現的細節。

公司專案需要開發出一套同時支援微信支付、支付寶支付、銀聯支付的sdk,既要滿足本公司專案需求,還需要提供給友方公司使用。

同時整合三家第三方的支付sdk,其中有大量的配置衝突需要解決。這篇文章通過demo和大家介紹一下如何開發自己的靜態庫.a檔案,分享給大家,同時對工作進行總結。

二:靜態庫實現

靜態庫生成demo
靜態庫使用demo

1. 新建一個靜態庫工程

開啟Xcode,點選FileNewProject,選擇iOSFramework & LibraryCocoa Touch Static Library新建一個靜態庫工程。

11.png

將工程命名為FBYSDKDemo,然後將工程儲存到一個空目錄下。
靜態庫工程由標頭檔案FBYSDKDemo.h和實現檔案FBYSDKDemo.m組成,這些檔案將被編譯為庫本身,如下圖:

22.png

在開發中,為了讓開發的靜態庫使用起來更方便,只需要讓使用者匯入一個標頭檔案,便可以訪問你所提供的介面,並且通過介面進行資料回撥。

2. 匯入標頭檔案

匯入UIKit的標頭檔案,這是建立一個庫所需要的。當你在建立不同的組成類時,你將會為它們新增到這個檔案中,確保它們能夠被庫的使用者獲取到。

開啟FBYSDKDemo.h,引入標頭檔案

#import <UIKit/UIKit.h>
複製程式碼

點選Build Phases,展開Link Binary with Libraries這一部分,點選+新增一個新的framework,找到UIKit.framework,點選add新增進來。

33.png

如果不結合標頭檔案,靜態庫是沒有用的,靜態庫編譯一組檔案,在這些檔案中類和方法都以二進位制資料的形式存在。
在靜態庫中類分為兩類,一類是公開的public,一類是私有的只能內部訪問使用。

接下來,需要在build欄中新增新的phase,來包含所有標頭檔案。
在Xcode的Build Phases介面,選擇EditorAdd Build PhaseAdd Headers Build Phase。

注意:如果發現按上面找到的選單項是不可點選的,如下圖:

44.png

點選下方Build Phases介面的白色區域來獲取Xcode的應用焦點,然後重新試一下

55.png

把FBYSDKDemo.h從專案中拖到Copy Headers下的Public部分。
這裡是要保證使用者可以使用庫中公開的類或者介面。

66.png

Copy Headers下的Public部分中所新增的類均是對外公開的。
這裡有三個分組,Public公開的,Private下的標頭檔案是可以被使用者看到的,Project下的檔案是私有的,這裡建議儘量將檔案放在Public和Project下。

3. 新增配置

新增配置主要是在Build Settings下操作,點選專案名,然後選擇FBYSDKDemo靜態庫目標,選擇Build Setting欄,然後搜尋public header,雙擊Public Headers Folder Path,在彈出檢視中鍵入如下內容

include/$(PROJECT_NAME)
複製程式碼

截圖如下:

77.png

因為你建立好的靜態檔案供他人使用,最好禁掉無效程式碼和debug符號,讓使用者自己選擇對自己的專案有利的部分使用。
在搜尋框中分別搜尋Dead Code Stripping、Strip Debug Symbol During Copy、Strip Style配置如下:

  • Dead Code Stripping設定為NO
  • Strip Debug Symbol During Copy 全部設定為NO
  • Strip Style設定為Non-Global Symbols

到目前為止,專案的構建已經完成,選擇目標為Generic iOS Device,按下command + B進行編譯,工程導航欄中Product目錄下libRWUIControls.a檔案將從紅色變為黑色,表明現在該檔案已經存在了。右鍵單擊libRWUIControls.a,選擇Show in Finder,如下圖所示:

83.png

上圖就可以看到對外公開的FBYSDKDemo.h類,其他實現類均以二進位制的形式在libFBYSDKDemo.a中。

4. 功能實現

這裡以實現靜態庫的開發為主,功能部分實現一個簡單的功能demo來舉例。

在標頭檔案FBYSDKDemo.h中實現如下程式碼:

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

typedef void (^FBYSDKCompletion)(NSString *result);

@interface FBYSDKDemo : NSObject

/**
 *
 *  @param urltype       網頁型別資訊 urltype可為iOS、Android
 *  @param completion    根據urltype獲取到相應網頁url結果回撥
 *
 */
- (void)urlType:(NSString *)urltype withCompletion:(FBYSDKCompletion)completion;

@end
複製程式碼

其中urltype為網頁型別資訊 urltype可為iOS、Android,根據urltype獲取到相應網頁url結果回撥completion。

在實現檔案FBYSDKDemo.m中程式碼如下:

#import "FBYSDKDemo.h"

@interface FBYSDKDemo ()

@end
@implementation FBYSDKDemo

- (void)urlType:(NSString *)urltype withCompletion:(FBYSDKCompletion)completion{
    
    if ([urltype isEqualToString:[NSString stringWithFormat:@"iOS"]]) {
        
        if (completion) {
            completion(@"https://juejin.im/post/5a41c04c6fb9a044fc44fd23");
        }
        
    }else if ([urltype isEqualToString:[NSString stringWithFormat:@"Android"]]) {
        
        if (completion) {
            completion(@"https://juejin.im/post/5a31e6adf265da430c11d41f");
        }
        
    }
    
}
@end
複製程式碼

選擇目標為Generic iOS Device,按下command + B進行編譯。

5. 合併靜態庫

選擇目標為Generic iOS Device,編譯執行後,右鍵單擊libRWUIControls.a,選擇Show in Finder顯示的libFBYSDKDemo.a可在真機,如果在虛擬機器中執行會報錯。

所以還要選擇目標為虛擬機器(例如iPhone 7),然後編譯執行,右鍵單擊libRWUIControls.a,選擇Show in Finder顯示的libFBYSDKDemo.a可在虛擬機器中執行,如果在真機中執行會報錯。

85.png

合併方法:開啟終端,輸入 lipo -create 真機庫.a的路徑 模擬器庫.a的路徑 -output 合成庫的名字(可以複製模庫.a的路徑,修改名字).a;回車就可以在模擬庫的資料夾中看到新合成的.a檔案了,如下圖:

87.png

合成後靜態庫檔案截圖如下:

86.png

libFBYSDKDemo_all.a檔案即為靜態庫檔案,一個通用的靜態庫.a就做好了。

三:靜態庫使用

1. 匯入靜態庫

匯入靜態庫和.h標頭檔案,注意下圖選項:

89.png

2. 呼叫函式

原始碼如下:

- (void)blogsBtn:(UIButton *)sender {
    
    if (sender.tag == 6000) {
        
        [FBYSDKDemo urlType:@"iOS" withCompletion:^(NSString *result) {
            
            [self contentURL:result];
            
        }];
    }else if (sender.tag == 6001) {
        
        [FBYSDKDemo urlType:@"Android" withCompletion:^(NSString *result) {
            
            [self contentURL:result];
        }];
    }
}
複製程式碼

result就是通過sdk回撥獲取到的結果。

3. DEMO截圖如下

DEMO截圖

4. 本篇文章demo原始碼:

靜態庫生成demo

靜態庫使用demo

希望可以幫助大家,如有問題可加QQ技術交流群: 668562416,如果哪裡有什麼不對或者不足的地方,還望讀者多多提意見或建議

如需轉載請聯絡我,經過授權方可轉載,謝謝

本篇已同步到個人部落格:FBY展菲


歡迎關注我的公眾號:網羅開發

iOS 靜態庫詳解與開發

相關文章