開(kāi)篇
想要構(gòu)建一個(gè)高逼格的應(yīng)用程序,庫(kù)的應(yīng)用必不可少,同時(shí)想要真正進(jìn)入iOS開(kāi)發(fā)的世界”庫(kù)“是我們要掌握的。

iOS中庫(kù)的相關(guān)概念
** 庫(kù) **:就是一段已經(jīng)編譯好的二進(jìn)制代碼,加上頭文件就可以提供給其他人使用了。iOS中常見(jiàn)的有 .a,.dylib,.Framework等結(jié)尾的庫(kù)。
** 庫(kù)的分類(lèi) **:開(kāi)源庫(kù)和閉源庫(kù)
**(1)開(kāi)源庫(kù) **:比如我們常用的AFNetworking,源碼都是開(kāi)發(fā)給我們開(kāi)發(fā)者的,下載后copy到項(xiàng)目中可以直接使用。在開(kāi)發(fā)中我們常用的是cocoapods,用命令直接導(dǎo)入開(kāi)源庫(kù),不用關(guān)心開(kāi)源庫(kù)的相關(guān)依賴(lài)。其實(shí)cocoapods的本質(zhì)是將開(kāi)源庫(kù)編譯成靜態(tài)庫(kù),然后使得主工程依賴(lài)此靜態(tài)庫(kù)。
**(2)閉源庫(kù) **:可以分為靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù),像我們開(kāi)發(fā)時(shí)用到的百度地圖等三方框架就會(huì)用到很多閉源庫(kù)。** 深入理解靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù) **
**(1)靜態(tài)庫(kù) **:它是你的.m文件編譯而成的二進(jìn)制文件集合,需要配合暴漏在外面的.h文件使用,在程序編譯的時(shí)候會(huì)被直接copy到目標(biāo)程序中,在編譯完成之后,庫(kù)文件實(shí)際就沒(méi)有多大作用了,目標(biāo)程序沒(méi)有外部依賴(lài),可以直接運(yùn)行,所以缺點(diǎn)就是導(dǎo)致目標(biāo)程序的體積增大。
**(2)動(dòng)態(tài)庫(kù) **:它也是你的.m文件編譯而成的二進(jìn)制文件集合,需要配合暴漏在外面的.h文件使用,但是不同的是,在編譯時(shí)動(dòng)態(tài)庫(kù)不會(huì)被copy到目標(biāo)程序中,目標(biāo)程序只會(huì)存儲(chǔ)指向動(dòng)態(tài)庫(kù)的引用,等到程序運(yùn)行時(shí),動(dòng)態(tài)庫(kù)才會(huì)被真正加載進(jìn)來(lái)。不會(huì)影響目標(biāo)程序的體積,但是會(huì)帶來(lái)一部分性能損失。而且目前蘋(píng)果不允許自制的動(dòng)態(tài)庫(kù)上架到AppStore** 使用靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)的好處 **
**(1)靜態(tài)庫(kù) **:模塊化,可以避免少量改動(dòng)經(jīng)常導(dǎo)致大量的重復(fù)編譯連接,也可以重用,但注意不是共享使用。
**(2)動(dòng)態(tài)庫(kù) **:可以將最終的可執(zhí)行文件體積縮小,多個(gè)應(yīng)用程序共享內(nèi)存中的同一份庫(kù)文件,達(dá)到節(jié)約資源的效果,也可以不重新編譯連接可執(zhí)行程序的前提下,更新動(dòng)態(tài)庫(kù)文件達(dá)到更新應(yīng)用程序的目的。但是可悲的是蘋(píng)果不允許自制的動(dòng)態(tài)庫(kù)上架到AppStore,但是可以開(kāi)發(fā)公司內(nèi)部的應(yīng)用程序還是比較方便的。
創(chuàng)建靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)
下面我們就先分別創(chuàng)建靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù),然后將我們創(chuàng)建的靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)應(yīng)用到我們的項(xiàng)目中,這樣便于大家更好的理解靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù),也方便大家更好的構(gòu)建自己的項(xiàng)目或框架
** 說(shuō)明 **:我寫(xiě)一個(gè)小Demo,Demo的功能是改變UIImage的顏色,我會(huì)分別創(chuàng)建靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)來(lái)實(shí)現(xiàn)不同的功能模塊(當(dāng)然,都可以創(chuàng)建為靜態(tài)庫(kù),但是為了讓大家更清楚兩種庫(kù)的創(chuàng)建步驟)
(1)靜態(tài)庫(kù):封裝資源文件(.bundle文件)用來(lái)存放圖片,封裝返回圖片路徑的方法并提供外界 .h 文件
(2)動(dòng)態(tài)庫(kù):封裝改變UIimage的顏色的方法并提供外界 .h 文件。
** 順便說(shuō)一下Bundle文件,Bundle文件是靜態(tài)的,也就是說(shuō),我們包含到包中的資源文件作為一個(gè)資源包是不參加項(xiàng)目編譯的。也就意味著,bundle包中不能包含可執(zhí)行的文件。它僅僅是作為資源,被解析成為特定的2進(jìn)制數(shù)據(jù)。**
- ** (1)創(chuàng)建靜態(tài)庫(kù) **
第一步:打開(kāi)Xcode,會(huì)彈出下面的選擇框,然后大家選擇標(biāo)記處,然后為靜態(tài)庫(kù)命名并創(chuàng)建。

創(chuàng)建成功后大家可以看到,Products下的libStaticLibraryTest.a文件是紅色的,不要方,command+B編譯或者run一下就好了,靜態(tài)庫(kù)是程序編譯是copy到目標(biāo)程序中的。如下圖,系統(tǒng)已經(jīng)為我們創(chuàng)建好了一個(gè)以工程名命名的 .h 和 .m 文件。你可以用也可以不用,我就直接用了

第二步:創(chuàng)建一個(gè)Bundle文件,command+N就會(huì)彈出下面的選擇框,然后選擇標(biāo)記并命名創(chuàng)建
![Uploading 屏幕快照 2016-11-17 上午1.06.21_068118.png . . .]

如下圖,Bundle文件創(chuàng)建成功后,我向其中放入一張圖片

第三步:添加Bundle文件到Copy File中,targets -> build phases -> copy files,如下圖所示

第四步:寫(xiě)相關(guān)方法
(1)在StaticLibraryTest.h提供對(duì)外方法接口
#import <Foundation/Foundation.h>
@interface StaticLibraryTest : NSObject
+ (NSString *)getImagePathWithBundleName:(NSString *)bundleName ImageName:(NSString *)imageName Type:(NSString *)type;
@end
(2)在StaticLibraryTest.m中實(shí)現(xiàn)方法
#import "StaticLibraryTest.h"
@implementation StaticLibraryTest
+ (NSString *)getImagePathWithBundleName:(NSString *)bundleName ImageName:(NSString *)imageName Type:(NSString *)type {
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:bundleName ofType:@"bundle"];
NSString *path = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, imageName, type];
return path;
}
@end
第五步:執(zhí)行程序,command+R,這樣我們的靜態(tài)庫(kù)就生成好了,點(diǎn)擊libStaticLibraryTest.a,然后show in fender,我們會(huì)看到下面我們生成了針對(duì)于模擬器的靜態(tài)庫(kù),注意我們command+R是在模擬器中run的,如果想生成針對(duì)真機(jī)的靜態(tài)庫(kù),必須在真機(jī)下run,然后可以通過(guò)lipo -create -output命令在終端合并兩個(gè)靜態(tài)庫(kù)文件,這樣我們就得到一個(gè)既可以在真機(jī)又可以在模擬器上使用的靜態(tài)庫(kù)了(這里不多說(shuō)了)。應(yīng)用時(shí)我們就將標(biāo)記處copy到我們的項(xiàng)目中,就可以直接使用了

- ** (2)創(chuàng)建動(dòng)態(tài)庫(kù) **
第一步:打開(kāi)Xcode,會(huì)彈出下面的選擇框,然后大家選擇標(biāo)記處,然后為靜態(tài)庫(kù)命名并創(chuàng)建。

創(chuàng)建完成后如圖所示

第二步:創(chuàng)建一個(gè)ChangeImageColor類(lèi),用來(lái)寫(xiě)改變圖片顏色的方法
ChangeImageColor.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface ChangeImageColor : NSObject
+ (UIImage *)changeImageColorWithColor:(UIColor *)color Image:(UIImage *)image;
@end
ChangeImageColor.m
#import "ChangeImageColor.h"
@implementation ChangeImageColor
+ (UIImage *)changeImageColorWithColor:(UIColor *)color Image:(UIImage *)image
{
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
CGContextClipToMask(context, rect, image.CGImage);
[color setFill];
CGContextFillRect(context, rect);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
@end
第三步:設(shè)置開(kāi)放的頭文件可以通過(guò)target—>build phases—>headers來(lái)設(shè)置,如下圖

同時(shí)可以在DynamicLibraryTest.h中倒入自己創(chuàng)建類(lèi)的頭文件

第四步:通用動(dòng)態(tài)庫(kù)
** 經(jīng)過(guò)以上三步我們只是創(chuàng)建了一個(gè)動(dòng)態(tài)庫(kù)文件,但是和靜態(tài)庫(kù)類(lèi)似,該動(dòng)態(tài)庫(kù)并同時(shí)不支持真機(jī)和模擬器,可以通過(guò)以下步驟創(chuàng)建通用動(dòng)態(tài)庫(kù) **
- 創(chuàng)建Aggregate,并命名創(chuàng)建。

- 設(shè)置Target Dependencies,targets -> Common -> Build Phases -> Target Dependencies,將動(dòng)態(tài)庫(kù)添加到Target Dependencies中

- 添加Run Script

- 添加腳本,復(fù)制粘貼就好
# Sets the target folders and the final framework product.
# 如果工程名稱(chēng)和Framework的Target名稱(chēng)不一樣的話,要自定義FMK_NAME,否則不需要改動(dòng)
FMK_NAME=${PROJECT_NAME}
# Install dir will be the final output to the framework.
# The following line create it in the root folder of the current project.
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
# Working dir will be deleted after the framework creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
# -configuration ${CONFIGURATION}
# Clean and Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build
# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
rm -r "${WRK_DIR}"
腳本添加完后,command+B執(zhí)行程序即可,在show in finder找到我們生成的動(dòng)態(tài)庫(kù),如圖,同樣我也只生成了模擬器的動(dòng)態(tài)庫(kù),和靜態(tài)庫(kù)原理相同,可通過(guò)終端來(lái)合成真機(jī)和模擬器共用的動(dòng)態(tài)庫(kù)

應(yīng)用靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)
通過(guò)以上步驟我們已經(jīng)分別生成了靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù),接下來(lái)我們就開(kāi)始運(yùn)用了,很簡(jiǎn)單,一步一步來(lái)就好.
- 第一步:創(chuàng)建一個(gè)工程,這里多說(shuō)了。
- 第二部:將靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)copy到工程中,添加后如圖所示

** 但是這時(shí)候需要注意了,靜態(tài)庫(kù)copy到文件中可以直接使用,但是對(duì)動(dòng)態(tài)庫(kù)必須添加依賴(lài)路徑**
- 第三步:添加完動(dòng)態(tài)庫(kù)后,同時(shí)設(shè)置將framework作為資源文件拷貝到Bundle中,Targets-->Build Phases-->Copy Bundle Resources,如下圖所示,

** 好了現(xiàn)在我們就將靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)copy到了我們的工程中,這時(shí)我們就可以使用了。**
項(xiàng)目實(shí)戰(zhàn)
接下來(lái)我在工程中的 ViewController.m 文件中代碼如下
#import "ViewController.h"
// 引入靜態(tài)庫(kù)中文件
#import "StaticLibraryTest.h"
// 引入動(dòng)態(tài)庫(kù)
#import <DynamicLibraryTest/DynamicLibraryTest.h>
@interface ViewController ()
@property (nonatomic, strong) UIImageView *imageOfTest;
@property (nonatomic, strong) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor whiteColor];
[self createSubView];
}
- (void)createSubView {
self.imageOfTest = [[UIImageView alloc] initWithFrame:CGRectMake((self.view.frame.size.width - 50) / 2, 200, 50, 50)];
// 靜態(tài)庫(kù)中提供的方法
NSString *imagePath = [StaticLibraryTest getImagePathWithBundleName:@"Resource" ImageName:@"advantage" Type:@"png"];
self.imageOfTest.image = [UIImage imageWithContentsOfFile:imagePath];
[self.view addSubview:self.imageOfTest];
self.button = [[UIButton alloc] initWithFrame:CGRectMake(20, 450, self.view.frame.size.width - 40, 50)];
self.button.backgroundColor = [UIColor cyanColor];
[self.button setTitle:@"change color" forState:UIControlStateNormal];
[self.view addSubview:self.button];
[self.button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonAction:(UIButton *)button {
NSLog(@"改變顏色");
UIImage *image = nil;
// 利用動(dòng)態(tài)庫(kù)中提供方法實(shí)現(xiàn)
if (button.selected == NO) {
image = [ChangeImageColor changeImageColorWithColor:[UIColor blueColor] Image:self.imageOfTest.image];
}
else {
image = [ChangeImageColor changeImageColorWithColor:[UIColor blackColor] Image:self.imageOfTest.image];
}
self.imageOfTest.image = image;
button.selected = !button.selected;
}
總結(jié)
這次博客寫(xiě)的長(zhǎng)了點(diǎn),也許不會(huì)有太好的閱讀效果,本來(lái)想拆分著寫(xiě)了,但是總感覺(jué)那樣對(duì)技術(shù)的提高不算大。希望大家諒解。