iOS開發(fā)中我們可以通過使用NSOperation/NSOperationQueue
來實現(xiàn)多線程加叁,是基于GCD的一套封裝揉燃。NSOperation是一個抽象類唇敞。使用的方式有三個:
- 使用子類 NSInvocationOperation
- 使用子類 NSBlockOperation
- 自定義繼承自 NSOperation 的子類,通過實現(xiàn)內(nèi)部相應(yīng)的方法來封裝操作启昧。
具體的使用推薦查看iOS 多線程:『NSOperation叙凡、NSOperationQueue』詳盡總結(jié)
我們在自定義一個operation時可以參考SDWebImage
庫里面的SDWebImageDownloaderOperation
。接下來列舉幾個使用注意點:
An operation object is a single-shot object—that is, it executes its task once and cannot be used to execute it again. You typically execute operations by adding them to an operation queue (an instance of the NSOperationQueue class)`
操作對象是單快照對象密末,即它只執(zhí)行一次任務(wù)握爷,不能用于再次執(zhí)行跛璧。通常通過將操作添加到操作隊列(NSOperationQueue類的實例)來執(zhí)行操作。
If you do not want to use an operation queue, you can execute an operation yourself by calling its start method directly from your code. Executing operations manually does put more of a burden on your code, because starting an operation that is not in the ready state triggers an exception.
如果不想使用操作隊列新啼,可以直接從代碼中調(diào)用操作的start方法來執(zhí)行操作追城。手動執(zhí)行操作會給代碼帶來更大的負擔(dān),因為啟動未處于就緒狀態(tài)的操作會觸發(fā)異常燥撞。
以上是官方的說明座柱,經(jīng)過測試代碼總結(jié)如下:
- 將一個已完成或者正在執(zhí)行的
NSOperation
添加到NSOperationQueue
中會拋出異常。 - 將一個已經(jīng)添加到queue中的
NSOperation
再次添加到queue中時會拋出異常物舒。 - 直接對
NSOperation
調(diào)用start方法時色洞,如果當(dāng)前NSOperation
未處于就緒狀態(tài)(ready=NO)會拋出異常,通常是否就緒跟添加的NSOperation
依賴有關(guān)系冠胯。 - 對設(shè)置了依賴關(guān)系的
NSOperation
之間火诸,設(shè)置優(yōu)先級不會起作用
NSOperation/NSOperationQueue
NSOperation
@property (readonly, getter=isCancelled) BOOL cancelled;
@property (readonly, getter=isExecuting) BOOL executing;
@property (readonly, getter=isFinished) BOOL finished;
- (void)addDependency:(NSOperation *)op;
- (void)removeDependency:(NSOperation *)op;
@property NSOperationQueuePriority queuePriority;
NSOperationQueue主要有兩種queue:mainQueue和自己創(chuàng)建的queue
- (void)addOperation:(NSOperation *)op;
- (void)cancelAllOperations;
@property NSInteger maxConcurrentOperationCount;
@property (getter=isSuspended) BOOL suspended;
相對于GCD,NSOperation/NSOperationQueue
的比較好用的功能:
- 可以使用KVO監(jiān)聽
NSOperation
的執(zhí)行狀態(tài)荠察。 - 可以設(shè)置
NSOperation
的優(yōu)先級置蜀,添加依賴。 - 可以擴展
NSOperation
的子類悉盆,重寫main或者start方法來完成對應(yīng)任務(wù)的封裝盯荤。 - 可以設(shè)置
NSOperationQueue
最大并發(fā)數(shù)maxConcurrentOperationCount來控制串行還是并發(fā),可以使隊列中的任務(wù)暫停suspended添加到線程中舀瓢。
在自定義NSOperation
子類時需要注意的是:
1. start和main方法的區(qū)別
系統(tǒng)的NSOperation
中的start方法中默認實現(xiàn)是會調(diào)用main方法廷雅,main方法結(jié)束耗美,就意味著NSOperation
執(zhí)行完畢京髓。
我們?nèi)绻远x的NSOperation
,通過重寫start方法商架,里面創(chuàng)建具體的任務(wù)堰怨,并且不要調(diào)用super去執(zhí)行main,因為main函數(shù)執(zhí)行完操作就結(jié)束了蛇摸。
而start方法就算執(zhí)行完畢备图,它的finish屬性也不會變,因此你可以控制這個operation的生命周期赶袄,在具體的異步任務(wù)完成之后手動cancel掉這個operation揽涮。