轉(zhuǎn)載自:NSOperation
我們都知道,讓程序瞬間加載并且快速響應(yīng)的秘訣在于后臺(tái)異步執(zhí)行途乃。
現(xiàn)在的OC開(kāi)發(fā)者一般有兩個(gè)選擇,分別是Grand Central Dispatch或者NSOperation
∪痈担現(xiàn)在GCD已經(jīng)逐漸發(fā)展成為主流了耍共。不過(guò)烫饼,我們今天要談的后者,一個(gè)面向?qū)ο蟮慕鉀Q辦法试读。
NSOperation表示了一個(gè)獨(dú)立的計(jì)算單元杠纵。作為一個(gè)抽象類,它給了它的子類一個(gè)十分有用而且線程安全的方式來(lái)建立狀態(tài)钩骇、優(yōu)先級(jí)比藻、依賴性和取消等的模型√纫伲或者银亲,你不是很喜歡再自己繼承NSOperation的話,框架還提供了NSBlockOperation纽匙,這是一個(gè)繼承自NSOperation且封裝了block的實(shí)體類务蝠。
很多執(zhí)行任務(wù)的案例都很好的運(yùn)用了NSOperation,包括網(wǎng)絡(luò)請(qǐng)求烛缔,圖像壓縮馏段,自然語(yǔ)言處理或者其他很多需要返回處理后數(shù)據(jù)的、可重復(fù)的践瓷、結(jié)構(gòu)化的院喜、相對(duì)長(zhǎng)時(shí)間運(yùn)行的任務(wù)。
但是僅僅把計(jì)算封裝進(jìn)一個(gè)對(duì)象而不做其他處理顯然沒(méi)有多大的用處晕翠,我們還需要NSOperationQueue來(lái)大顯身手喷舀。
NSOperationQueue控制著這些并行操作的執(zhí)行,它扮演著優(yōu)先級(jí)隊(duì)列的角色崖面,讓它管理的高優(yōu)先級(jí)操作(NSOperation -queuePriority)能優(yōu)先于低優(yōu)先級(jí)的操作運(yùn)行的情況下元咙,使它的管理操作能基本遵循先進(jìn)先出的原則執(zhí)行。此外巫员,在你設(shè)置了能并行運(yùn)行的操作的最大值(maxConcurrentOperationCount)之后庶香,NSOperationQueue還能并行執(zhí)行操作。
讓一個(gè)NSOperation操作開(kāi)始简识,你可以直接調(diào)用-start赶掖,或者將它添加到NSOperationQueue中,添加之后七扰,它會(huì)在隊(duì)列排到它以后自動(dòng)執(zhí)行奢赂。
現(xiàn)在讓我們通過(guò)怎樣使用和怎樣通過(guò)繼承實(shí)現(xiàn)功能來(lái)看看NSOperation稍微復(fù)雜的部分。
狀態(tài)
NSOperation包含了一個(gè)十分優(yōu)雅的狀態(tài)機(jī)來(lái)描述每一個(gè)操作的執(zhí)行颈走。
isReady → isExecuting → isFinished
為了替代不那么清晰的state屬性膳灶,狀態(tài)直接由上面那些keyPath的KVO通知決定,也就是說(shuō),當(dāng)一個(gè)操作在準(zhǔn)備好被執(zhí)行的時(shí)候轧钓,它發(fā)送了一個(gè)KVO通知給isReady的keypath序厉,讓這個(gè)keypath和對(duì)應(yīng)的屬性isReady在訪問(wèn)的時(shí)候返回YES。
每一個(gè)屬性對(duì)于其他的屬性必須是互相獨(dú)立不同的毕箍,也就是同時(shí)只可能有一個(gè)屬性返回YES弛房,從而才能維護(hù)一個(gè)連續(xù)的狀態(tài):- isReady: 返回 YES 表示操作已經(jīng)準(zhǔn)備好被執(zhí)行, 如果返回NO則說(shuō)明還有其他先前的相關(guān)步驟沒(méi)有完成。 - isExecuting: 返回YES表示操作正在執(zhí)行而柑,反之則沒(méi)在執(zhí)行文捶。 - isFinished : 返回YES表示操作執(zhí)行成功或者被取消了,NSOperationQueue只有當(dāng)它管理的所有操作的isFinished屬性全標(biāo)為YES以后操作才停止出列媒咳,也就是隊(duì)列停止運(yùn)行粹排,所以正確實(shí)現(xiàn)這個(gè)方法對(duì)于避免死鎖很關(guān)鍵。
取消
早些取消那些沒(méi)必要的操作是十分有用的伟葫。取消的原因可能包括用戶的明確操作或者某個(gè)相關(guān)的操作失敗恨搓。
與之前的執(zhí)行狀態(tài)類似,當(dāng)NSOperation的-cancle狀態(tài)調(diào)用的時(shí)候會(huì)通過(guò)KVO通知isCancelled的keypath來(lái)修改isCancelled屬性的返回值筏养,NSOperation需要盡快地清理一些內(nèi)部細(xì)節(jié)斧抱,而后到達(dá)一個(gè)合適的最終狀態(tài)。特別的渐溶,這個(gè)時(shí)候isCancelled和isFinished的值將是YES辉浦,而isExecuting的值則為NO。
有一件肯定需要注意的事情就是關(guān)于單詞“cancel”的拼法特性茎辐,盡管各類英語(yǔ)的習(xí)慣不盡相同宪郊,但是對(duì)于NSOperation來(lái)說(shuō):-cancel:方法調(diào)用里只需要一個(gè)L(東西)- isCancelled:屬性里需要兩個(gè)L(形同詞)。
優(yōu)先級(jí)
不可能所有的操作都是一樣重要拖陆,通過(guò)以下的順序設(shè)置queuePriority屬性可以加快或者推遲操作的執(zhí)行:
- NSOperationQueuePriorityVeryHigh
- NSOperationQueuePriorityHigh
- NSOperationQueuePriorityNormal
- NSOperationQueuePriorityLow
- NSOperationQueuePriorityVeryLow
此外弛槐,有些操作還可以指定threadPriority的值,它的取值返回可以從0.0到1.0依啰,1.0代表最高的優(yōu)先級(jí)乎串。鑒于queuePriority屬性決定了操作執(zhí)行的順序,threadPriority則指定了當(dāng)前操作開(kāi)始執(zhí)行以后的CPU計(jì)算能力的分配速警,如果你不知道這是什么叹誉,好吧,你可能根本沒(méi)必要知道這是什么闷旧。
依賴性
根據(jù)你應(yīng)用的復(fù)雜度不同长豁,將大任務(wù)再分成一系列子任務(wù)一般都是很有意義的,而你能通過(guò)NSOperation的依賴性實(shí)現(xiàn)忙灼。
比如說(shuō)匠襟,對(duì)于服務(wù)器下載并壓縮一張圖片的整個(gè)過(guò)程 ,你可能會(huì)將這個(gè)整個(gè)過(guò)程分為兩個(gè)操作(可能你還會(huì)用到這個(gè)網(wǎng)絡(luò)子過(guò)程再去下載另一張圖片宵距,然后用壓縮子過(guò)程去壓縮磁盤(pán)上的圖片)秘症。顯然圖片需要等到下載完成之后才能被調(diào)整尺寸,所以我們定義網(wǎng)絡(luò)子操作的依賴,通過(guò)代碼來(lái)說(shuō)就是:
[resizingOperation addDependency:networkingOperation];
[operationQueue addOperation:networkingOperation];
[operationQueue addOperation:resizingOperation];
除非一個(gè)操作的依賴的isFininished返回YES父腕,不然這個(gè)操作不會(huì)開(kāi)始。時(shí)時(shí)牢記將所有的依賴關(guān)系添加到操作隊(duì)列很重要青瀑,不然會(huì)像走路遇到一條大溝璧亮,就走不過(guò)去了幺。
此外斥难,確保不要意外地創(chuàng)建依賴循環(huán)枝嘶,像A依賴B,B又依賴A哑诊,這也會(huì)導(dǎo)致悲劇的死鎖群扶。
completionBlock
有一個(gè)在iOS 4和Snow Leopard新加入的十分有用的功能就是completionBlock屬性。
每當(dāng)一個(gè)NSOperation執(zhí)行完畢镀裤,它就會(huì)調(diào)用它的completionBlock屬性一次竞阐,這提供了一個(gè)非常好的方式讓你能在視圖控制器(ViewController)里或者模型(Model)里加入自己更多的自己的邏輯代碼。比如說(shuō)暑劝,你可以在一個(gè)網(wǎng)絡(luò)請(qǐng)求操作的completionBlock來(lái)處理操作執(zhí)行完以后從服務(wù)器下載下來(lái)的數(shù)據(jù)骆莹。
對(duì)于現(xiàn)在OC程序員必須掌握的工具中,NSOperation依然是最基本的一個(gè)担猛。盡管GCD對(duì)于內(nèi)嵌異步操作十分理想幕垦,NSOperation依舊提供更復(fù)雜、面向?qū)ο蟮挠?jì)算模型傅联,它對(duì)于涉及到各種類型數(shù)據(jù)先改、需要重復(fù)處理任務(wù)又是更加理想的。在你的下一個(gè)項(xiàng)目里使用它吧蒸走,讓它及帶給用戶歡樂(lè)仇奶,你自己也會(huì)很開(kāi)心的。