NSOperationQueue简介
1.概述:?NSOperationQueue類管理NSOperation對象的執(zhí)行。NSOperationQueue可以被稱為操作隊(duì)列,NSOperation可以被稱為操作。操作被添加到操作隊(duì)列之后,操作隊(duì)列會根據(jù)操作對象的優(yōu)先級或者相互之間的依賴關(guān)系來執(zhí)行操作。一個應(yīng)用程序可以創(chuàng)建多個操作隊(duì)列,每個操作隊(duì)列分別管理若干操作。
2.什么時候操作會被移除:?當(dāng)操作被添加到隊(duì)列中以后,我們不能從操作隊(duì)列中直接移除操作對象。當(dāng)一個操作對象的任務(wù)完成之后才會被自動移除。任務(wù)完成的含義:操作的start方法被調(diào)用,并且isFinished方法返回YES。
3.如何取消任務(wù)執(zhí)行:調(diào)用操作對象cancel方法并不能使操作馬上停止執(zhí)行。當(dāng)NSOperation的cancel方法被調(diào)用后,如果操作不在隊(duì)列中,這個方法會將操作的isFinished設(shè)為YES,如果在操作隊(duì)列中,這個方法會將操作對象的isCancelled狀態(tài)設(shè)為YES,并且isReady設(shè)為YES,讓隊(duì)列調(diào)用它的start方法。在start或者main方法實(shí)現(xiàn)中,我們應(yīng)該檢查isCancelled和isFinished屬性,如果任意一個為YES,就不執(zhí)行操作,直接返回,如果是并發(fā)操作,讓isFinished方法返回YES,如果是非并發(fā)操作,設(shè)置isFinished值為YES。
4.操作隊(duì)列的相關(guān)API:(1)創(chuàng)建隊(duì)列:可以調(diào)用[[NSOperationQueue alloc] init]方法新建一個操作隊(duì)列,或者調(diào)用類方法currentQueue、mainQueue方法獲取現(xiàn)存的操作隊(duì)列。currentQueue一般在NSOperation對象子類中調(diào)用,用來返回啟動當(dāng)前操作的隊(duì)列,如果NSOperation在非運(yùn)行狀態(tài)或者在NSOperation外部調(diào)用此方法,一般會返回nil。mainQueue方法返回和主線程綁定的操作隊(duì)列。(2)增加操作:addOperation: ?增加一個操作對象。addOperations:waitUntilFinished: 增加一個操作對象數(shù)組,可以阻塞當(dāng)前線程等待所有操作完成。addOperationWithBlock: 以block的方式添加操作,blcok必須為無參數(shù)無返回?cái)?shù)據(jù)。(3)最大并發(fā)數(shù):maxConcurrentOperationCount :最大并發(fā)數(shù)屬性,默認(rèn)為-1,表示并發(fā)數(shù)無限制,由系統(tǒng)根據(jù)環(huán)境條件動態(tài)決定。setMaxConcurrentOperationCount:設(shè)置最大并發(fā)數(shù)。(4)其它:operations :獲取添加到隊(duì)列中的所有操作對象。operationCount :獲取添加到隊(duì)列中的操作對象的數(shù)量。setSuspended: 設(shè)置隊(duì)列是否暫停安排操作執(zhí)行。isSuspended :獲取隊(duì)列是否處在暫停安排操作執(zhí)行的狀態(tài)。cancelAllOperations:調(diào)用所有操作對象的cancel方法。waitUntilAllOperationsAreFinished:阻塞當(dāng)前線程,等待所有操作都完成。
5.KVO兼容的屬性operations - 只讀operationCount - 只讀maxConcurrentOperationCount - 可讀寫suspended - 可讀寫name -可讀寫
6.內(nèi)部實(shí)現(xiàn):?在iOS4.0及以后,NSOperationQueue內(nèi)部實(shí)現(xiàn)使用GCD,iOS4.0之前,使用NSThread實(shí)現(xiàn)。
二、NSOperation簡介
1.概述:NSOperation類代表單個任務(wù)對象,是一個抽象類,因此他不能直接使用它,可以實(shí)現(xiàn)它的子類,也可以使用類庫中已存在的子類,比如NSInvocationOperation和NSBlockOperation,可以比較簡單的創(chuàng)建操作對象。操作對象只能被執(zhí)行一次,只要被執(zhí)行過,就不能再重新執(zhí)行第二次。
2.依賴關(guān)系:(1)調(diào)用NSOperation的addDependency或者removeDependency可以給一個操作對象添加一個它所依賴的操作對象、刪除一個所依賴的操作對象。調(diào)用dependencies方法可以獲取一個操作所依賴的所有操作對象。(2)只有當(dāng)一個操作對象的所有依賴對象都執(zhí)行完畢后,它的isReady屬性才可能會成為YES,從而被隊(duì)列執(zhí)行。(3)NSOperation本身并不區(qū)分它的依賴對象是執(zhí)行失敗還是成功,只判斷操作是否執(zhí)行完畢(即有可能是通過cancel方法完成的)。(4)如果一個操作對象被調(diào)用了cancel方法,但是還有它依賴的操作對象沒有完成,它所依賴的操作對象將被忽略,當(dāng)前操作對象不再等待它們完成。
3.執(zhí)行優(yōu)先級(1)調(diào)用queuePriority、setQueuePriority:方法可以獲取和設(shè)置操作對象的執(zhí)行優(yōu)先級。(2)類庫中定義了幾個優(yōu)先級變量:? ?NSOperationQueuePriorityVeryLow? ?NSOperationQueuePriorityLow? ?NSOperationQueuePriorityNormal? ?NSOperationQueuePriorityHigh? ?NSOperationQueuePriorityVeryHigh? ?最高對應(yīng)的數(shù)字為8,最低-8,如果手動設(shè)置數(shù)字,setQueuePriority方法會自動切換成對應(yīng)的最合適的數(shù)字。(3)優(yōu)先級只表示此操作對象的優(yōu)先級和其它對象優(yōu)先級的大小關(guān)系,不能精確定義兩個對象的執(zhí)行順序,不能使用優(yōu)先級這個方式來實(shí)現(xiàn)依賴關(guān)系。
4.KVO兼容的屬性isCancelled - 只讀,操作是不是被取消,cancel方法會改變此變量。isConcurrent - 只讀,是不是并發(fā)isExecuting - 只讀,是不是正在執(zhí)行isFinished - 只讀,是不是已經(jīng)完成isReady - 只讀,是不是已經(jīng)準(zhǔn)備好執(zhí)行dependencies - 只讀,操作對象的依賴關(guān)系queuePriority - 可讀寫,操作對象在隊(duì)列中的優(yōu)先級completionBlock - 可讀寫,操作完成之后執(zhí)行的Block
5.并發(fā)操作和非并發(fā)操作(1)如果打算手動執(zhí)行操作對象,我們可以把操作對象設(shè)計(jì)成非并發(fā)的,也可以涉及成并發(fā)的。操作對象默認(rèn)是非并發(fā)的。(2)在非并發(fā)的操作對象中,操作任務(wù)是以同步的方式實(shí)現(xiàn)的,當(dāng)調(diào)用start方法時,任務(wù)在當(dāng)前線程執(zhí)行,當(dāng)start方法返回時,任務(wù)已經(jīng)完成,執(zhí)行期間線程被阻塞。(3)并發(fā)操作對象的任務(wù)以異步的方式執(zhí)行,當(dāng)調(diào)用start方法時,start方法立即返回,不阻塞當(dāng)前線程。因?yàn)樵趕tart方法中,任務(wù)代碼使用新線程或者異步API實(shí)現(xiàn)。(4)如果打算總是以隊(duì)列的方式執(zhí)行操作,最簡單的方式是將操作對象設(shè)計(jì)成非并發(fā)的。定義并發(fā)操作對象需要更過的工作,因?yàn)閷?shí)現(xiàn)并發(fā)操作對象需要實(shí)現(xiàn)更多的方法,而且我們必須去監(jiān)聽任務(wù)的狀態(tài)以及使用KVO手動通知的方式報(bào)告狀態(tài)。當(dāng)非并發(fā)操作在隊(duì)列中執(zhí)行時,隊(duì)列會自動建立新線程來執(zhí)行操作,最后結(jié)果也是異步的。所以如果總是以隊(duì)列的方式執(zhí)行操作對象,是沒有理由使用并發(fā)操作的。
6.子類化NSOperation(1)如果是非并發(fā)操作,只需要實(shí)現(xiàn)main方法即可。(2)如果是并發(fā)操作,最少要實(shí)現(xiàn)一下四個方法:start、isConcurrent、isExecuting、isFinished。(3)在main方法和start方法實(shí)現(xiàn)中,在開始執(zhí)行任務(wù)代碼前,首先應(yīng)該檢查對象狀態(tài),如果isCancelled等于YES或者isFinished等于YES,則不用執(zhí)行任務(wù)代碼。如果是并發(fā)操作,讓isFinished方法返回YES,如果是非并發(fā)操作,設(shè)置isFinished值為YES。(4)在重寫isConcurrent、isExecuting、isFinished方法的同時,還要對值發(fā)生改變的key使用KVO手動的方式觸發(fā)通知,否則操作不會被認(rèn)為執(zhí)行結(jié)束。代碼邏輯:在以上三個方法中通過判斷本地的狀態(tài)標(biāo)記變量來判斷狀態(tài)值,并返回;在更改我們的本地標(biāo)記變量值時,通過KVO發(fā)送通知,然后OperationQueue就會去調(diào)用以上三個方法來判斷Operation執(zhí)行狀態(tài),如果isFinished方法返回YES,則操作完成,任務(wù)結(jié)束。
7.異步NSOperation實(shí)現(xiàn)示例:
typedef enum
{
? ? RequestStateReady = 0,
? ? RequestStateExecuting,
? ? RequestStateFinished
}RequestState;
@interface RequestOperation ()
@property(nonatomic,strong) NSURLConnection *connection;
@property(nonatomic,strong) NSMutableData *resultData;
@property(nonatomic,assign) RequestState requestState;
@end
@implementation RequestOperation
-(id)init{
? ? self = [super init];
? ? if (self) {
? ? ? ? [self willChangeValueForKey:@"isReady"];
? ? ? ? self.requestState = RequestStateReady;
? ? ? ? [self didChangeValueForKey:@"isReady"];
? ? }
? ? return self;
}
#pragma mark - Operation實(shí)現(xiàn)父類方法
-(void)start{
? ? [self exeRequest];
}
-(BOOL)isConcurrent{
? ? return YES;
}
-(BOOL)isReady{
? ? return self.requestState == RequestStateReady && [super isReady];
}
-(BOOL)isExecuting{
? ? return self.requestState == RequestStateExecuting;
}
-(BOOL)isFinished{
? ? return self.requestState == RequestStateFinished;
}
#pragma mark - 發(fā)起請求
-(void)exeRequest{
? ? if (self.isCancelled == YES || self.isFinished == YES) {
? ? ? ? return;
? ? }
?? ?
? ? NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.baidu.com/"]];
? ? self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
? ? [self.connection start];
? ? [[NSRunLoop currentRunLoop] run];
?? ?
? ? [self willChangeValueForKey:@"isExecuting"];
? ? self.requestState = RequestStateExecuting;
? ? [self didChangeValueForKey:@"isExecuting"];
}
#pragma mark - 請求代理實(shí)現(xiàn)
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
? ? self.resultData = [[NSMutableData alloc] initWithCapacity:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
? ? [self.resultData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
? ? [self willChangeValueForKey:@"isFinished"];
? ? self.requestState = RequestStateFinished;
? ? [self didChangeValueForKey:@"isFinished"];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
? ? [self willChangeValueForKey:@"isFinished"];
? ? self.requestState = RequestStateFinished;
? ? [self didChangeValueForKey:@"isFinished"];
}
@end
總結(jié)
以上是生活随笔為你收集整理的NSOperationQueue简介的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [记录] --- linux上项目
- 下一篇: 将iOS默认上下文坐标系改变为Quart