前面介紹了ios中三種多線程技術(shù)的NSThread,本文將繼續(xù)介紹NSOperation的使用纫事。
環(huán)境信息:
Mac OS X 10.10.1
Xcode 6.1.1
iOS 8.1
正文:
一渗鬼、NSOperation的簡(jiǎn)介
NSOperation的抽象程度高于NSThread览露,它是蘋果對(duì)線程的一個(gè)面向?qū)ο蠓庋b。NSOperation表示一個(gè)獨(dú)立的計(jì)算單元譬胎,作為一個(gè)抽象類差牛,你需要實(shí)例話他的子類 ?NSInvocationOperation / ?NSBlockOperation 來(lái)進(jìn)行具體操作命锄。實(shí)例化之后,調(diào)用start方法或者加入到一個(gè)NSOperationQueue 操作隊(duì)列中偏化,就可以開(kāi)始執(zhí)行脐恩。
二、NSOperation的使用
1.直接啟動(dòng)一個(gè)NSInvocationOperation
// 如果直接調(diào)用operation的start方法侦讨,是在主線程上運(yùn)行驶冒,不會(huì)開(kāi)啟新的線程
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadLoadImage:) object:imageView];
[op start];
2.使用NSOperationQueue管理NSOperation并開(kāi)啟一個(gè)異步線程
// 定義操作隊(duì)列屬性
@property (strong, nonatomic) NSOperationQueue *queue;
// 實(shí)例化操作隊(duì)列
self.queue = [[NSOperationQueue alloc] init];
// 初始化一個(gè)NSInvocationOperation
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadLoadImage:) object:imageView];
// 將NSInvocationOperation添加到隊(duì)列,一添加到隊(duì)列搭伤,就會(huì)開(kāi)啟新線程執(zhí)行任務(wù)只怎,不可以同時(shí)使用start
[self.queue addOperation:op];
3.使用NSOperationQueue管理并NSBlockOperation開(kāi)啟一個(gè)線程
NSBlockOperation與NSInvocationOperation沒(méi)有什么本質(zhì)差別,只是NSBlockOperation使用代碼塊會(huì)更方便一些
// 初始化一個(gè)NSBlockOperation
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
// 異步操作
[self operationLoadImage:imageView];
}];
// 添加操作到隊(duì)列中
[self.queue addOperation:op];
4.在主線程中執(zhí)行操作
// 在主線程隊(duì)列上更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[imageView setImage:image];
}];
5.添加線程之間的依賴關(guān)系
直接在隊(duì)列中添加操作會(huì)并發(fā)執(zhí)行怜俐,誰(shuí)先誰(shuí)后是系統(tǒng)調(diào)用的身堡,在特定的時(shí)候我們需要控制操作的執(zhí)行順序,就會(huì)使用到addDependency操作拍鲤。addDependency: 是NSOperation的成員方法贴谎,調(diào)用該方法的NSOperation對(duì)象將在參數(shù)執(zhí)行完成之后執(zhí)行。需要先添加依賴關(guān)系季稳,再將操作添加到隊(duì)列中擅这。
// 初始化三個(gè)塊操作
NSBlockOperation *op1 =[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下載 %@", [NSThread currentThread]);
}];
NSBlockOperation *op2 =[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"美化 %@", [NSThread currentThread]);
}];
NSBlockOperation *op3 =[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"更新 %@", [NSThread currentThread]);
}];
// 通過(guò)添加依賴可以控制線程執(zhí)行順序,依賴關(guān)系可以多重依賴
// 注意:不要建立循環(huán)依賴景鼠,會(huì)造成死鎖
[op2 addDependency:op1];
[op3 addDependency:op2];
// 直接加到隊(duì)列里面會(huì)并發(fā)執(zhí)行仲翎,誰(shuí)先先后是系統(tǒng)調(diào)用決定
[self.queue addOperation:op3];
[self.queue addOperation:op1];
[self.queue addOperation:op2];
6.控制線程并發(fā)數(shù)
// 并發(fā)的線程越多越耗資源,隊(duì)列可以設(shè)置同時(shí)并發(fā)線程的數(shù)量铛漓,來(lái)進(jìn)行控制
self.queue.maxConcurrentOperationCount = 1;
7.取消一個(gè)操作
NSOperation里有一系列的屬性用來(lái)標(biāo)明自身狀態(tài)的溯香,isReady → ?isExecuting →??isFinish。線程start后并不是立即執(zhí)行浓恶,而是進(jìn)入一個(gè)就緒的狀態(tài)(isReady)玫坛,由系統(tǒng)調(diào)度執(zhí)行。有時(shí)可能需要進(jìn)行取消操作包晰,可以調(diào)用– (void)cancel; 來(lái)停止一些還未執(zhí)行的不必要的線程湿镀。
for (NSOperation *operation in self.queue.operations) {
// 取消一個(gè)NSOperation
[operation cancel];
}
8.給NSOperation添加完成代碼塊
比如在下載一本小說(shuō)結(jié)束的時(shí)候,你需要發(fā)個(gè)通知告訴用戶已經(jīng)下載完畢伐憾,這時(shí)就可以使用NSOperation的completionBlock屬性來(lái)執(zhí)行操作勉痴。
operation.completionBlock = ^{
NSLog(@"完成");
};
9.優(yōu)先級(jí)
同NSThread一樣,NSOperation可以通過(guò)threadPriority屬性來(lái)指定優(yōu)先級(jí)塞耕。但是在IOS8蚀腿,線程這個(gè)概念已經(jīng)被蘋果框架系統(tǒng)性的忽略了,threadPriority已由NSQualityOfService屬性替代,下面是NSQualityOfService的幾個(gè)幾個(gè)枚舉莉钙。
typedef NS_ENUM(NSInteger, NSQualityOfService) {
/* 和圖形處理相關(guān)的任務(wù)廓脆,比如滾動(dòng)和動(dòng)畫 */
NSQualityOfServiceUserInteractive = 0x21,
/* 用戶請(qǐng)求的任務(wù),但是不需要精確到毫秒級(jí)磁玉。例如如果用戶請(qǐng)求打開(kāi)電子郵件App來(lái)查看郵件 */
NSQualityOfServiceUserInitiated = 0x19,
/* 周期性的用戶請(qǐng)求任務(wù)停忿。比如,電子郵件App可能被設(shè)置成每5分鐘自動(dòng)檢測(cè)新郵件蚊伞。但是在系統(tǒng)資源極度匱乏的時(shí)候席赂,將這個(gè)周期性的任務(wù)推遲幾分鐘也沒(méi)有大礙*/
NSQualityOfServiceUtility = 0x11,
/* 后臺(tái)任務(wù),對(duì)這些任務(wù)用戶可能并不會(huì)察覺(jué)时迫,比如電子郵件App對(duì)郵件進(jìn)行索引以方便搜索 */
NSQualityOfServiceBackground = 0x09,
/* 默認(rèn)的優(yōu)先級(jí) */
NSQualityOfServiceDefault = -1
} NS_ENUM_AVAILABLE(10_10, 8_0);
三颅停、NSOperation小結(jié)
1.NSOperation方便控制線程執(zhí)行順序
2.使用NSBlockOperation可以使用塊代碼,不必單寫線程方法掠拳,便于傳遞多個(gè)參數(shù)
3.可以控制線程并發(fā)數(shù)癞揉,有效地對(duì)線程進(jìn)行控制
4.可以添加線程完成代碼塊,執(zhí)行需要的操作
雖然GCD已經(jīng)成為流行溺欧, 但是在某些框架中喊熟,例如AFNetworking還是使用的NSOperation來(lái)完成線程相關(guān)的操作,除了使用框架的NSInvocationOperation / ?NSBlockOperation 來(lái)處理線程操作姐刁,你也可以通過(guò)集成來(lái)完成你需要的操作芥牌。