六月潮濕天氣的日數比五月多,比四月也多烫沙。周四晚踢足球匹层,深圳多雨,中午電閃雷鳴雨不停锌蓄,有人建議取消場地升筏,我想雨后終究會見到彩虹,不一會瘸爽,雨停您访。
項目需求提供framework,記錄下過程剪决。
一灵汪、什么是庫?
庫是共享程序代碼的方式柑潦,一般分為靜態(tài)庫和動態(tài)庫享言。
二、靜態(tài)庫和動態(tài)庫的區(qū)別渗鬼?
靜態(tài)庫:鏈接時完整地拷貝至可執(zhí)行文件中览露,被多次使用就有多分拷貝冗余拷貝。
動態(tài)庫:鏈接不復制譬胎,程序運行時由系統(tǒng)動態(tài)加載到內存差牛,供程序調用命锄,系統(tǒng)只加載一次,多個程序共用多糠,節(jié)省內存累舷。
三浩考、iOS里靜態(tài)庫形式夹孔?
.a和.framework
四、iOS里動態(tài)庫形式析孽?
.dylib和.framework
五搭伤、framework為么可以既是靜態(tài)庫有事動態(tài)庫?
系統(tǒng)的.framework是動態(tài)庫袜瞬,我們自己建立的.framework是靜態(tài)庫怜俐。
六、.a與.framework有什么區(qū)別邓尤?
.a是一個純二進制文件拍鲤,.framework中除了有二進制文件之外還有資源文件。
.a文件不能直接使用汞扎,至少要有.h文件配合季稳,.framework文件可以直接使用。
.a + .h + sourceFile = .framework澈魄。
建議用.framework景鼠。
七、為什么要使用靜態(tài)庫痹扇?
方便共享代碼铛漓,便于合理使用。
實現iOS程序的模塊化鲫构∨ǘ瘢可以把固定的業(yè)務模塊化成靜態(tài)庫。和別人分享你的代碼庫结笨,但不想讓別人看到你代碼的實現问顷。開發(fā)第三方sdk的需要。
提供給接入方使用的是文件禀梳,一般是一個.framework和一個同名的.bundle文件杜窄。
1、嵌入包含.bundle的framework到接入方的embeded binaries里面算途,剛開始想著是否能只提供一個.framework文件塞耕,bundle包含在里面∽烊浚可是可以扫外,只是需要將打出來的.framework導入到embeded binaries中莉钙。但是接入此.framework后,打包會報錯。
點擊show logs筛谚,did not contain a "archived-expanded-entitlements.xcent" resource
解決辦法:一個static的libraryxxx.framework被添加在Embedded Binaries里面了磁玉,從Embedded Binaries移除framework,添加在Link Frameworks and Libraries里面驾讲。
只能作罷蚊伞,只有動態(tài)庫能放到embeded binaries中,Xcode也能制作動態(tài)庫吮铭,只是不能上傳AppStore时迫。
通過嵌入embeded binaries里面打出來的,最后形成.app文件右鍵顯示包內容之后和可以看到一個Frameworks的文件夾谓晌。里面有嵌入embeded binaries的所有framework掠拳。
- 新建一個workspace,添加兩個project:CVideoProject,CVideoDemoProject纸肉。在CVideoProject中添加一個target:CVideoBundle溺欧。相當于總共有三個target,方便調試。
1.新建靜態(tài)庫:static framework柏肪。
2.修改配置信息
每次build時不是只生成支持一種設備的framework
添加framework支持所有類型設備姐刁。
arm64:iPhone6s | iphone6s plus|iPhone6| iPhone6 plus|iPhone5S | iPad Air| iPad mini2(iPad mini with Retina Display)
armv7s:iPhone5|iPhone5C|iPad4(iPad with Retina Display)
armv7:iPhone4|iPhone4S|iPad|iPad2|iPad3(The New iPad)|iPad mini|iPod Touch 3G|iPod Touch4
i386是針對intel通用微處理器32位處理器
x86_64是針對x86架構的64位處理器
模擬器32位處理器測試需要i386架構,
模擬器64位處理器測試需要x86_64架構预吆,
真機32位處理器需要armv7,或者armv7s架構龙填,
真機64位處理器需要arm64架構。
需要暴露給接入方使用的頭文件移到public路徑中拐叉。
3.在framework中新建bundle岩遗。
導入用到的資源文件
修改bundle文件的參數配置
編譯bundle target生成bundle。
編譯framework發(fā)現framework中包含bundle凤瘦。
1宿礁、將bundle放入到framework中,打出來的framework中包含bundle蔬芥,此時代碼里面引入圖片的路徑有變梆靖。在workspace的Demo中的embeded binaries引入framework。
通過打開CVideoDemo.app顯示包內容發(fā)現如果嵌入到embeded binaries中的framework都放在一個frameworks文件夾路徑下笔诵。而CVideo.bundle就在Frameworks/CVideo.framework路徑下返吻,圖片的路徑據此找到。
-(void)setupBackNaviBar
{
self.navigationItem.leftBarButtonItem = nil;
self.backView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 44)];
CVideoAddAreaButton *backButton=[CVideoAddAreaButton buttonWithType:UIButtonTypeCustom];
backButton.shouldExpandClickArea = YES;
[backButton setFrame:CGRectMake(0, 0, 44, 44)];
[backButton setImage:[CVideoBundle CVideoImageWithName:@"icon_back"] forState:UIControlStateNormal];
[backButton addTarget:self action:@selector(onNaviBack) forControlEvents:UIControlEventTouchUpInside];
[self.backView addSubview:backButton];
self.closeButton=[CVideoAddAreaButton buttonWithType:UIButtonTypeCustom];
self.closeButton.shouldExpandClickArea = NO;
[self.closeButton setFrame:CGRectMake(32, 0, 44, 44)];
[self.closeButton setImage:[CVideoBundle CVideoImageWithName:@"icon_close"] forState:UIControlStateNormal];
[self.closeButton addTarget:self action:@selector(closeButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.backView addSubview:self.closeButton];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:self.backView];
}
+ (NSString *)CVideoBundlePathForResource:(NSString *)name ofType:(NSString *)type {
NSString *bundlePath = [self getCVideoBundlePath];
return [[NSBundle bundleWithPath:bundlePath] pathForResource:name ofType:type];
}
+ (UIImage *)CVideoImageWithName:(NSString *)name {
//bundle放入framework中乎婿,framework嵌入embeded binaries中的圖片路徑
name = [NSString stringWithFormat:@"%@@%dx", name, (int)[UIScreen mainScreen].scale];
NSString *imagePath = [CVideoBundle CVideoBundlePathForResource:name ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
//bundle單獨拖入Demo中的bundle路徑
// NSString *imagePath = [NSString stringWithFormat:@"%@/%@",[self getCVideoBundlePath],name];
// UIImage *image = [UIImage imageNamed:imagePath];
return image;
}
+ (NSString *)getCVideoBundlePath {
static NSString *bundlePath;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//bundle放入framework中测僵,framework嵌入embeded binaries中的bundle路徑
bundlePath = [[NSBundle mainBundle] pathForResource:@"Frameworks/CVideo.framework/CVideo" ofType:@"bundle"];
//bundle單獨拖入Demo中的bundle路徑
// bundlePath = [[NSBundle mainBundle] pathForResource:@"CVideo" ofType:@"bundle"];
});
return bundlePath;
}
2、顯然,雖然將bundle放入framework中,提供給接入方只需要提供framework文件給接入方而不需要提供bundle文件捍靠,但是打包的時候會報錯沐旨,所以還是要將bundle和framework分開提供。
- 圖片的路徑榨婆。
-(void)setupBackNaviBar
{
self.navigationItem.leftBarButtonItem = nil;
self.backView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 44)];
CVideoAddAreaButton *backButton=[CVideoAddAreaButton buttonWithType:UIButtonTypeCustom];
backButton.shouldExpandClickArea = YES;
[backButton setFrame:CGRectMake(0, 0, 44, 44)];
[backButton setImage:[CVideoBundle CVideoImageWithName:@"icon_back"] forState:UIControlStateNormal];
[backButton addTarget:self action:@selector(onNaviBack) forControlEvents:UIControlEventTouchUpInside];
[self.backView addSubview:backButton];
self.closeButton=[CVideoAddAreaButton buttonWithType:UIButtonTypeCustom];
self.closeButton.shouldExpandClickArea = NO;
[self.closeButton setFrame:CGRectMake(32, 0, 44, 44)];
[self.closeButton setImage:[CVideoBundle CVideoImageWithName:@"icon_close"] forState:UIControlStateNormal];
[self.closeButton addTarget:self action:@selector(closeButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.backView addSubview:self.closeButton];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:self.backView];
}
+ (NSString *)CVideoBundlePathForResource:(NSString *)name ofType:(NSString *)type {
NSString *bundlePath = [self getCVideoBundlePath];
return [[NSBundle bundleWithPath:bundlePath] pathForResource:name ofType:type];
}
+ (UIImage *)CVideoImageWithName:(NSString *)name {
//bundle放入framework中磁携,framework嵌入embeded binaries中的圖片路徑
name = [NSString stringWithFormat:@"%@@%dx", name, (int)[UIScreen mainScreen].scale];
// NSString *imagePath = [CVideoBundle CVideoBundlePathForResource:name ofType:@"png"];
// UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
//bundle單獨拖入Demo中的bundle路徑
NSString *imagePath = [NSString stringWithFormat:@"%@/%@",[self getCVideoBundlePath],name];
UIImage *image = [UIImage imageNamed:imagePath];
return image;
}
+ (NSString *)getCVideoBundlePath {
static NSString *bundlePath;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//bundle放入framework中,framework嵌入embeded binaries中的bundle路徑
// bundlePath = [[NSBundle mainBundle] pathForResource:@"Frameworks/CVideo.framework/CVideo" ofType:@"bundle"];
//bundle單獨拖入Demo中的bundle路徑
bundlePath = [[NSBundle mainBundle] pathForResource:@"CVideo" ofType:@"bundle"];
});
return bundlePath;
}