一:介紹
1. 什麼是庫?
庫是共享程式程式碼的方式,一般分為靜態庫和動態庫。
靜態庫:連結時完整地拷貝至可執行檔案中,被多次使用就有多份冗餘拷貝。
動態庫:連結時不復制,程式執行時由系統動態載入到記憶體,供程式呼叫,系統只載入一次,多個程式共用,節省記憶體。
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檔案,分享給大家,同時對工作進行總結。
二:靜態庫實現
1. 新建一個靜態庫工程
開啟Xcode,點選FileNewProject,選擇iOSFramework & LibraryCocoa Touch Static Library新建一個靜態庫工程。
將工程命名為FBYSDKDemo,然後將工程儲存到一個空目錄下。
靜態庫工程由標頭檔案FBYSDKDemo.h和實現檔案FBYSDKDemo.m組成,這些檔案將被編譯為庫本身,如下圖:
在開發中,為了讓開發的靜態庫使用起來更方便,只需要讓使用者匯入一個標頭檔案,便可以訪問你所提供的介面,並且通過介面進行資料回撥。
2. 匯入標頭檔案
匯入UIKit的標頭檔案,這是建立一個庫所需要的。當你在建立不同的組成類時,你將會為它們新增到這個檔案中,確保它們能夠被庫的使用者獲取到。
開啟FBYSDKDemo.h,引入標頭檔案
#import <UIKit/UIKit.h>
複製程式碼
點選Build Phases,展開Link Binary with Libraries這一部分,點選+新增一個新的framework,找到UIKit.framework,點選add新增進來。
如果不結合標頭檔案,靜態庫是沒有用的,靜態庫編譯一組檔案,在這些檔案中類和方法都以二進位制資料的形式存在。
在靜態庫中類分為兩類,一類是公開的public,一類是私有的只能內部訪問使用。
接下來,需要在build欄中新增新的phase,來包含所有標頭檔案。
在Xcode的Build Phases介面,選擇EditorAdd Build PhaseAdd Headers Build Phase。
注意:如果發現按上面找到的選單項是不可點選的,如下圖:
點選下方Build Phases介面的白色區域來獲取Xcode的應用焦點,然後重新試一下
把FBYSDKDemo.h從專案中拖到Copy Headers下的Public部分。
這裡是要保證使用者可以使用庫中公開的類或者介面。
Copy Headers下的Public部分中所新增的類均是對外公開的。
這裡有三個分組,Public公開的,Private下的標頭檔案是可以被使用者看到的,Project下的檔案是私有的,這裡建議儘量將檔案放在Public和Project下。
3. 新增配置
新增配置主要是在Build Settings下操作,點選專案名,然後選擇FBYSDKDemo靜態庫目標,選擇Build Setting欄,然後搜尋public header,雙擊Public Headers Folder Path,在彈出檢視中鍵入如下內容
include/$(PROJECT_NAME)
複製程式碼
截圖如下:
因為你建立好的靜態檔案供他人使用,最好禁掉無效程式碼和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,如下圖所示:
上圖就可以看到對外公開的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可在虛擬機器中執行,如果在真機中執行會報錯。
合併方法:開啟終端,輸入 lipo -create 真機庫.a的路徑 模擬器庫.a的路徑 -output 合成庫的名字(可以複製模庫.a的路徑,修改名字).a;回車就可以在模擬庫的資料夾中看到新合成的.a檔案了,如下圖:
合成後靜態庫檔案截圖如下:
libFBYSDKDemo_all.a檔案即為靜態庫檔案,一個通用的靜態庫.a就做好了。
三:靜態庫使用
1. 匯入靜態庫
匯入靜態庫和.h標頭檔案,注意下圖選項:
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截圖如下
4. 本篇文章demo原始碼:
希望可以幫助大家,如有問題可加QQ技術交流群: 668562416,如果哪裡有什麼不對或者不足的地方,還望讀者多多提意見或建議
如需轉載請聯絡我,經過授權方可轉載,謝謝
本篇已同步到個人部落格:FBY展菲
歡迎關注我的公眾號:網羅開發