前言
上一節(jié)我們通過把代碼簡單的拆分上傳至github
赎线,通過cocoapods
的遠程私有庫缔御,把拆分的代碼當作第三方庫供我們使用蚜枢,但是這種方式存在很多問題竟块,實際項目使用這種簡單粗暴的拆分也不可取壶运,所以今天講上一篇博客提到的第二種私有庫創(chuàng)建方式,后面統(tǒng)一把私有庫稱作組件浪秘。
最后大概結構
本文要講的是改變組件創(chuàng)建的方式蒋情,解決:
- 組件使用
.framework
或者.a
這兩種靜態(tài)庫的方式創(chuàng)建 - 組件單獨依賴第三方,即有自己的
podfile
文件配置使用 - 組件有自己單獨的資源文件耸携,在自己組件中使用資源文件
- 組件工程調(diào)試及配置使用
吐槽部分可跳過
關于創(chuàng)建靜態(tài)庫的方式:
- 使用pod命令也就是
pod lib
命令創(chuàng)建 - 自己通過
xcode
手動創(chuàng)建
兩種方式也無所謂好壞棵癣,都能夠達到創(chuàng)建組件的目的。我想要說的是手動創(chuàng)建好處:
- 手動創(chuàng)建可以知道創(chuàng)建過程都做了什么违帆,
pod
命令如果不去深究不能很明白原理浙巫。 -
pod
命令創(chuàng)建的組件只能放在Development Pods
文件夾目錄下
,對于手動創(chuàng)建使用target
依賴的方式的方式來說顯得不是很友好刷后。 -
pod
命令創(chuàng)建的組件要添加資源文件時配置麻煩的畴,手動創(chuàng)建簡單。
當然手動創(chuàng)建也有缺點:
-
pod
命令創(chuàng)建方便快捷尝胆,手動創(chuàng)建相對步驟多 - 創(chuàng)建和編譯過程需要踩坑丧裁。
總結:
- 如果是單純抽取一些小東西用命令就可以沒必要折騰
- 如果項目要大規(guī)模使用組件化建議手動創(chuàng)建方式
正文
上面說過創(chuàng)建組件靜態(tài)庫有兩種,一種是.framwework另外一種是.a含衔,兩種方式創(chuàng)建大同小異煎娇。這里先以創(chuàng)建.a靜態(tài)庫的方式創(chuàng)建,相關節(jié)點配置不同點我會說明贪染。
創(chuàng)建
打開xcode創(chuàng)建進入選擇創(chuàng)建菜單
上圖中Cocoa Touch Framework
就是創(chuàng)建.framework
靜態(tài)庫的方式缓呛,我們先創(chuàng)建.a形式的靜態(tài)庫 選中Cocoa Touch Static Library
點擊 next
,填寫你組件靜態(tài)庫的名稱完成杭隙。
創(chuàng)建好之后像這樣:
初始文件:
- 幫我們創(chuàng)建和靜態(tài)庫名稱一樣的文件夾和類(頭文件)哟绊。
- 把創(chuàng)建的頭文件加入到
Copy Files
里面,這里要關心的一點是痰憎,如果你修改了頭文件這里也要添加相應你要暴露的頭文件票髓,這里的頭文件可以是多個也就是你想暴露多少個就添加多少個。
添加podfile:
使用pod init
命令在根目錄添加 podfile
,這里簡單添加Masonry
platform :ios, '8.0'
target 'StaticKit' do
pod 'Masonry'
end
進行pod install
命令之后我們可以看到pod
給我們黃色的警告
主要是前面的錯誤:
[!] The Podfile contains framework or static library targets (StaticKit), for which the Podfile does not contain host targets (targets which embed the framework).
If this project is for doing framework development, you can ignore this message. Otherwise, add a target to the Podfile that embeds these frameworks to make this message go away (e.g. a test target).
這大概的意思是說當前的target
為靜態(tài)庫铣耘,而且pod
依賴的是當前這個靜態(tài)庫不是依賴host targets
洽沟,host targets
我的理解是可執(zhí)行的target
,當時我沒注意這個警告以為是普通的警告,之后添加到殼工程的時候會提示該靜態(tài)庫的pod
找不到蜗细。
當然最后如果我們認真看提示的警告已經(jīng)告訴了我們解決的辦法了裆操,最后一行的括號內(nèi)(e.g. a test target)
。這就是讓我們創(chuàng)建一個測試的target
然pod
依賴它就可以讓這個警告消失炉媒。這個很多網(wǎng)上文章都是一筆帶過沒說清楚的踪区,不然就是不提靜態(tài)庫添加第三方依賴的問題,當然我的解釋也不一定對橱野。
靜態(tài)庫需要添加一個測試target
讓第三方依賴
添加測試target
:
點擊+
按鈕進入選擇target
菜單
選中iOS Unit Testing Bundle
取名為 StaticKitTests
創(chuàng)建好之后是這樣
修改podfile
重新更新
platform :ios, '8.0'
project 'StaticKit'
#修改為測試的target
target 'StaticKitTests' do
pod 'Masonry'
end
更新后的 pod
信息朽缴,發(fā)現(xiàn)已經(jīng)正常了
到這里如果你把Masonry 導入項目的類的時候會發(fā)現(xiàn)提示無法找到頭文件,這時候我們要設置Heaser Search Paths 設置路徑 添加 "$(SRCROOT)/Pods/Headers/Public"
添加資源文件:
添加資源文件我一般可以簡單創(chuàng)建一個bundle放到工程目錄下水援,使用時添加工程下就行了密强。這種方式很簡單也是可以用的,但是這樣的方式不容易管理我們的資源文件蜗元。在這里我推薦把資源文件也當作一個target
添加到靜態(tài)庫組件中或渤,過程和上面創(chuàng)建測試target
差不多只是需要一些配置。
點擊+
好到創(chuàng)建target
界面,tab頁選中macOS
下面的 Bundle
,下一步 我取名為StaticKit_res
按自己需要可以改名字
創(chuàng)建好之后是這樣的
創(chuàng)建的時候你可以看到我們創(chuàng)建的是macOS
的bundle
奕扣,至于為什么要用mac
不用iOS
很簡單因為iOS
沒有這個選項薪鹦,所以為了適配iOS
我們需要做下面兩個配置
- 配置
Base SDK
為iOS
配置路徑看下圖
- 一般我們圖片有
@2x
@3x
這樣放在bundle
會導致讀取圖片失敗,所以我們要改下配置,把COMBINE_HIDPI_IMAGES
設置為NO
讀取資源文件:
我們的組件的資源文件基礎配置已經(jīng)好了池磁,接下來要添加一個工具類來讀取資源了奔害,在這里我們以讀取圖片資源為例,其他的資源大同小異地熄。
- 我們添加幾張測試圖片放到
staticKit_res
文件夾下华临,記得target
的選擇
- 創(chuàng)建我們的工具類名稱為
StaticKitHelper
代碼如下
@interface StaticKitHelper : NSObject
+ (NSBundle *)resBundle:(Class)classtype;
+ (UIImage*)imageName:(NSString*)name;
@end
#import "StaticKitHelper.h"
@implementation StaticKitHelper
+ (NSBundle *)resBundle:(Class)classtype {
static NSBundle *framworkBundle = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
framworkBundle = [NSBundle bundleForClass:classtype];
if (framworkBundle) {
NSString *resourceBundlePath = [framworkBundle pathForResource:@"StaticKit_res" ofType:@"bundle"];
if (resourceBundlePath && [[NSFileManager defaultManager] fileExistsAtPath:resourceBundlePath]) {
framworkBundle = [NSBundle bundleWithPath:resourceBundlePath];
}
}
});
return framworkBundle;
}
+ (UIImage*)imageName:(NSString*)name {
if (name.length == 0) {
return nil;
}
NSBundle *bundle = [StaticKitHelper resBundle:[self class]];
NSString *path = [bundle pathForResource:name ofType:@"png"];
return [UIImage imageWithContentsOfFile:path];
}
@end
//調(diào)用
UIImage *image = [StaticKitHelper imageName:@"PlayButtonOverlayLarge"];
添加測試代碼:
通過上面的設置我們的.a靜態(tài)庫組件基礎配置已經(jīng)好了,接下來我們要添加測試代碼端考,我這里把默認的頭文件普通的類改成一個控制器類雅潭,設置背景為藍色,并添加了一張圖片:
#import "StaticKit.h"
#import "StaticKitHelper.h"
#import <Masonry/Masonry.h>
@implementation StaticKit
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"StaticKit控制器";
UIImage *image = [StaticKitHelper imageName:@"PlayButtonOverlayLarge"];
UIImageView *imageView = [UIImageView new];
imageView.image = image;
[self.view addSubview:imageView];
[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(100);
make.top.equalTo(self.view).offset(100);
make.size.mas_equalTo(CGSizeMake(40, 40));
}];
self.view.backgroundColor = [UIColor blueColor];
}
@end
到這里StaticKit組件已經(jīng)是一個合格的靜態(tài)庫組件了却特,它可以參與模塊的開發(fā)了扶供,最后總結下大概的步驟:
- 打開
xcode
創(chuàng)建Cocoa Touch Static Library
設置組件名字 - 添加測試
target
,創(chuàng)建podfile
設置依賴的target
為測試StaticKitTests
- 添加資源文件
target
StaticKit_res 設置兩個編譯參數(shù)裂明,導入測試圖片 - 添加讀取資源工具類椿浓,添加測試代碼
- 編寫的代碼在自己的靜態(tài)庫組件內(nèi)編譯通過
添加殼工程調(diào)試:
- 準備工作
所謂的殼工程就是我平常創(chuàng)建可以直接運行的工程,你可以隨便創(chuàng)建一個帶導航欄的控制器漾岳,用于push
到我們的靜態(tài)庫組件供調(diào)試轰绵,這個步驟很簡單就不廢話了默認你已經(jīng)創(chuàng)建好了殼工程。
- 添加到殼工程
- 打開殼工程將
StaticKit.xcodeproj
拖到殼工程下
- 點擊殼工程選中
Build Phases
在Target Dependencies
下點+
號 添加StaticKit
和StaticKit_res
- 在同一個地方的
Link Binary With Libraries
添加StaticKit
- 在靜態(tài)庫中的
Products
文件夾下的StaticKit_res
拖到Copy Bundle Resources
下
- 編譯下如果顯示成功就算大功告成了尼荆,如果有報錯你可以回頭看上面那個步驟做錯了或者漏了左腔。
這里解釋下
第一步?jīng)]什么好解釋的。
第二步是我們把兩個target
當作子target
依賴殼工程捅儒。
第三步表示代碼執(zhí)行我們鏈接的是StacKit
這個target
而不包含StaticKit_res
液样。
第四步是把我們靜態(tài)庫的資源文件添加到mainBundle
里面這樣我們才可以通過代碼找得到它。
添加殼工程測試代碼:
//第三方方式訪問巧还,這個頭文件在我們創(chuàng)建的時候有說要設置才能訪問
#import <StaticKit/StaticKit.h>
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"點擊跳轉到庫";
}[圖片上傳中...(show.gif-f0b9fe-1530268184126-0)]
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
StaticKit *sk = [[StaticKit alloc]init];
[self.navigationController pushViewController:sk animated:YES];
}
@end
運行截圖
到這里自己手動創(chuàng)建.a靜態(tài)庫的全過程就完了筐高,接下來會說.a靜態(tài)庫和.framework靜態(tài)庫配置悍汛,framework的創(chuàng)建和.a基本流程是一致的柑船,某些配置有細微差別杭抠。
.framework靜態(tài)庫的差異
- framework的靜態(tài)庫創(chuàng)建的時候默認都是動態(tài)的,但是上架是不允許動態(tài)的所以我要在
Build Settings
里面的Mach-O Type
設置為Static Library
2.framework設置的頭文件不一樣阶牍,framework創(chuàng)建的時候頭文件都會默認顯示在Project
下我們需要把它拖到Public
下
3.最后一個不同點就是加人殼工程是frameworkKit.framework
不需要加入到Target Dependencies
下
本文到這里就交代完手動創(chuàng)建靜態(tài)庫到調(diào)試的全部內(nèi)容了喷面,如果有寫錯的地方或者有什么問題你可以在本文下方評論,也希望大家都交流學習走孽。下篇帶大家編譯靜態(tài)庫到遠程私有庫惧辈,敬請期待!
參考資料
https://www.raywenderlich.com/65964/create-a-framework-for-ios
https://github.com/jverkoey/iOS-Framework