NSOperation是一個(gè)抽象類日戈,代表與單個(gè)任務(wù)相關(guān)聯(lián)的代碼和數(shù)據(jù)第步。
由于NSOperation是一個(gè)抽象類,所以不直接使用它而是使用它的子類或者系統(tǒng)定義的子類(NSInvocationOperation或者NSBlockOperation)來(lái)執(zhí)行任務(wù)贸人,盡管是一個(gè)抽象類跌穗,NSOperation的基本實(shí)現(xiàn)包含了重要的邏輯來(lái)協(xié)調(diào)任務(wù)安全的執(zhí)行。這種內(nèi)置的邏輯使得我們可以專注于任務(wù)的具體實(shí)現(xiàn)懒鉴。
operation對(duì)象是一次性對(duì)象诡挂,也就是說(shuō)它只執(zhí)行一次任務(wù),不能重復(fù)使用临谱。通常把operation添加到一個(gè) 操作隊(duì)列(NSOperationQueue 類的實(shí)例)來(lái)執(zhí)行璃俗。 操作隊(duì)列 可以在子線程中直接執(zhí)行操作,或者使用GCD間接的執(zhí)行悉默。
如果不想使用操作隊(duì)列城豁,我們可以直接在代碼中調(diào)用operation的start
方法來(lái)執(zhí)行操作。 手動(dòng)執(zhí)行操作確實(shí)給代碼帶來(lái)更多的負(fù)擔(dān)抄课。因?yàn)閱?dòng)一個(gè)未ready狀態(tài)的操作會(huì)引發(fā)異常唱星。ready
屬性指示操作的準(zhǔn)備情況
操作依賴性
依賴性是以特定順序執(zhí)行操作的便捷方式。 可以使用- (void)addDependency:(NSOperation *)op;
和- (void)removeDependency:(NSOperation *)op;
方法來(lái)為操作添加或移除依賴跟磨。默認(rèn)情況下间聊,operation對(duì)象直到它依賴的所有的operation對(duì)象都執(zhí)行完畢之后才會(huì)被視為準(zhǔn)備就緒。一旦最后依賴的操作完成抵拘,該operation對(duì)象就準(zhǔn)備就緒并能夠執(zhí)行
NSOperation的依賴關(guān)系不區(qū)分關(guān)聯(lián)操作是否成功finished哎榴。(換句話說(shuō),取消某個(gè)操作也會(huì)被標(biāo)記為finished)。在其依賴操作被取消或未成功完成任務(wù)的情況下尚蝌,是否繼續(xù)執(zhí)行具有依賴關(guān)系的操作取決于我們自己迎变。這可能需要將一些額外的錯(cuò)誤跟蹤功能添加到operation對(duì)象
KVO 兼容屬性
NSOperation類的幾個(gè)屬性是支持KVC和KVO的,根據(jù)需要飘言,我們可以監(jiān)測(cè)這些屬性來(lái)控制應(yīng)用程序的其他部分衣形。使用一下路徑監(jiān)測(cè)屬性:
isCancelled - read-only
isAsynchronous - read-only
isExecuting - read-only
isFinished - read-only
isReady - read-only
dependencies - read-only
queuePriority - readable and writable
completionBlock - readable and writable
雖然我們可以觀察這些屬性,但是不應(yīng)該將這些屬性跟UI元素綁定姿鸿,因?yàn)橥ǔG闆r下UI元素的操作只能在主線程谆吴,而KVO通知可能在任何線程中。
如果為任何上述屬性提供自定義實(shí)現(xiàn)般妙,則自定義實(shí)現(xiàn)必須支持KVC和KVO纪铺。 如果自定義的NSOperation對(duì)象定義了其他屬性相速,建議也使這些屬性支持KVC和KVO碟渺。
多核考慮
NSOperation類本身是多核的。因此多線程訪問(wèn)是安全的突诬,不需要?jiǎng)?chuàng)建額外的鎖來(lái)同步訪問(wèn)苫拍。之所以這么設(shè)計(jì)是因?yàn)閛peration通常在創(chuàng)建并正在監(jiān)視它的單獨(dú)線程中運(yùn)行。
當(dāng)子類化NSOperation類時(shí)旺隙,必須確保重寫的方法是線程安全的绒极。如果在子類中實(shí)現(xiàn)了自定義的方法,必須確定這些方法是線程安全的蔬捷。因此垄提,必須同步訪問(wèn)operation的任何數(shù)據(jù)變量,以防止?jié)撛诘臄?shù)據(jù)損壞周拐。
異步和同步操作
如果要手動(dòng)執(zhí)行operation铡俐,而不是將其添加到一個(gè)隊(duì)列中。則可以將operation設(shè)計(jì)為是同步或異步執(zhí)行妥粟。 operation對(duì)象默認(rèn)是同步的审丘,在同步操作中,operation對(duì)象不會(huì)創(chuàng)建一個(gè)單獨(dú)的線程來(lái)執(zhí)行任務(wù)勾给。當(dāng)你調(diào)用同步操作的start
方法時(shí)滩报,該操作會(huì)在當(dāng)前線程立即執(zhí)行。當(dāng)對(duì)象的start
方法將控制權(quán)交還給調(diào)用者時(shí)播急,它本身的任務(wù)就完成了
當(dāng)調(diào)用異步操作的start
方法時(shí)脓钾,該方法可能會(huì)在其相應(yīng)的任務(wù)完成之前返回。異步操作對(duì)象負(fù)責(zé)在單獨(dú)的線程上調(diào)度它的任務(wù)桩警。該操作可以通過(guò)直接開(kāi)啟新的線程可训,調(diào)用異步方法,或?qū)lock提交到調(diào)度隊(duì)列執(zhí)行來(lái)實(shí)現(xiàn)。當(dāng)控制權(quán)返回給調(diào)用者時(shí)沉噩,操作是否正在進(jìn)行并不重要捺宗,只是它可能正在運(yùn)行。
如果使用隊(duì)列來(lái)執(zhí)行operation川蒙,使用同步操作更簡(jiǎn)單蚜厉。如果手動(dòng)執(zhí)行操作,則可能需要將操作定義為異步畜眨。 定義一個(gè)異步操作需要更多工作昼牛,因?yàn)楸仨毐O(jiān)測(cè)任務(wù)的持續(xù)狀態(tài),并且使用KVO通知監(jiān)測(cè)該狀態(tài)下的更改康聂。但是贰健,如果想要確保手動(dòng)執(zhí)行的操作不會(huì)阻塞線程,異步操作將會(huì)很有用恬汁。
當(dāng)添加一個(gè)操作到操作隊(duì)列中伶椿,隊(duì)列會(huì)忽略操作的asynchronous
屬性的值, 并始終從一個(gè)單獨(dú)的線程調(diào)用start
方法。 因此氓侧,如果將operation添加到操作隊(duì)列中來(lái)執(zhí)行的話脊另,就沒(méi)有理由使這些operation異步。
子類化說(shuō)明
NSOperation類提供了追蹤操作執(zhí)行狀態(tài)的基本邏輯约巷,但是除此之外偎痛,必須子類化來(lái)完成實(shí)際工作。如何創(chuàng)建子類取決于操作是并發(fā)執(zhí)行還是非并發(fā)執(zhí)行独郎。
重寫的方法
對(duì)于非并發(fā)操作踩麦,通常只需要重寫一個(gè)方法:
- (void)main;
在這個(gè)方法中,放置執(zhí)行給定任務(wù)所需的代碼氓癌。當(dāng)然谓谦,也可以自定義初始化方法,來(lái)方便的創(chuàng)建實(shí)例顽铸。我們可能還需要定義一些getter和setter方法來(lái)訪問(wèn)operation中的數(shù)據(jù)茁计,但是,如果定義了自定義的getter/setter方法谓松,必須保證這些方法是線程安全的
如果創(chuàng)建并發(fā)操作星压,則需要至少覆蓋以下方法和屬性
- (void)start;
@property(readonly, getter=isAsynchronous) BOOL asynchronous;
@property(readonly, getter=isExecuting) BOOL executing;
@property(readonly, getter=isFinished) BOOL finished;
在并發(fā)操作中,start
方法負(fù)責(zé)以異步方式啟動(dòng)操作鬼譬。無(wú)論是生成一個(gè)線程還是調(diào)用一個(gè)異步方法娜膘,都可以通過(guò)該方法來(lái)完成。開(kāi)始操作時(shí)优质,start
方法應(yīng)該更新executing
屬性(表示操作的執(zhí)行狀態(tài))竣贪【荩可以通過(guò)發(fā)送KVO通知,讓外部知道操作正在運(yùn)行演怎。executing
屬性必須是線程安全的匕争。
完成或取消任務(wù)后,并發(fā)操作對(duì)象必須為isExecuting
和isFinished
路徑生成KVO通知爷耀,標(biāo)記操作狀態(tài)的最終更改甘桑。(在取消的情況下,即使操作沒(méi)有結(jié)束它的任務(wù)歹叮,也要更新isFinished
跑杭。 排隊(duì)的操作在從隊(duì)列中刪除之前必須是已經(jīng)finished)。除了生成KVO通知咆耿,重寫的executing
和finished
屬性也應(yīng)該根據(jù)操作狀態(tài)作出相應(yīng)的更改德谅。
重點(diǎn):
在自定義的
start
方法中,任何時(shí)候都不應(yīng)該調(diào)用super萨螺。當(dāng)定義一個(gè)并發(fā)操作窄做,需要自己提供跟默認(rèn)start
方法相同的行為,其中包括啟動(dòng)任務(wù)并生成合適的KVO通知屑迂。自定義的start
方法也應(yīng)該檢查在實(shí)際啟動(dòng)任務(wù)之前操作本身是否已經(jīng)被取消浸策。
即使是并發(fā)隊(duì)列,也很少需要重寫上述描述以外的方法惹盼。 然而,如果你自定義operation 的依賴功能惫确,則還必須重寫其他的方法和提供KVO通知手报。在有依賴關(guān)系的情況下,可能只需要提供isReady
路徑的通知改化。 因?yàn)?code>dependencies屬性包含了依賴操作的列表掩蛤,對(duì)它的更改已由默認(rèn)的NSOperation
類處理
維護(hù)operation對(duì)象狀態(tài)
operation對(duì)象在內(nèi)部維護(hù)狀態(tài)信息以確定什么時(shí)候執(zhí)行操作是安全的,并通過(guò)operation的生命周期通知外部客戶的進(jìn)展情況陈肛。自定義的子類需要維護(hù)該狀態(tài)信息以確保代碼中的操作正確的執(zhí)行揍鸟。 相關(guān)的operation狀態(tài)的key path:
-
@property (readonly, getter=isReady) BOOL ready;
isReady
路徑指示操作何時(shí)可以執(zhí)行。ready 屬性在操作準(zhǔn)備好執(zhí)行的時(shí)候?yàn)閠rue,如果仍存在有未完成的操作依賴于它則為false句旱。
-
@property(readonly, getter=isExecuting) BOOL executing;
isExecuting
屬性指示操作是否正在處理其分配的任務(wù)阳藻。executing
屬性在operation正在執(zhí)行任務(wù)時(shí)為true,否則為false如果你自定義了operation對(duì)象的
start
方法谈撒,則當(dāng)operation的執(zhí)行狀態(tài)更改時(shí)腥泥,還必須更新executing
屬性并生成KVO通知。
-
@property(readonly, getter=isFinished) BOOL finished;
isFinished
路徑指示某個(gè)操作已成功完成它的任務(wù)啃匿,或者已取消并正在退出蛔外。 operation對(duì)象不會(huì)清除一個(gè)依賴蛆楞,直到isFinished
為true。同樣的夹厌,一個(gè)操作隊(duì)列不會(huì)把一個(gè)operation出列豹爹,直到finished
屬性為true。因此矛纹,將operation標(biāo)記為finished 對(duì)于防止隊(duì)列進(jìn)行備份或取消操作至關(guān)重要帅戒。如果你替換了
start
方法或操作對(duì)象,當(dāng)操作結(jié)束執(zhí)行或取消操作時(shí)生成KVO通知如果替換
start
方法或操作對(duì)象崖技,則還必須替換finished
屬性逻住,并在操作結(jié)束執(zhí)行或取消操作時(shí)生成KVO通知。
-
@property (readonly, getter=isCancelled) BOOL cancelled;
isCancelled
路徑指示operation的取消被請(qǐng)求迎献。不必為該路徑發(fā)送KVO通知瞎访。
響應(yīng)取消命令
一旦添加operation到隊(duì)列中,operation就脫離你的控制了吁恍。隊(duì)列會(huì)接管并處理任務(wù)的調(diào)度扒秸。但是,如果稍后決定不想執(zhí)行operation冀瓦,可能是因?yàn)橛脩酎c(diǎn)擊取消按鈕或退出了應(yīng)用程序伴奥,比如,你可以取消operation來(lái)防止它不必要的占用CPU時(shí)間翼闽∈搬悖可以通過(guò)operation對(duì)象的cancel
方法或- (void)cancelAllOperations;
方法。
取消一個(gè)operation不會(huì)立即強(qiáng)制停止正在執(zhí)行的操作感局。代碼中必須顯式的檢查該屬性的值并根據(jù)需要中止尼啡。NSOperation
的默認(rèn)實(shí)現(xiàn)包括檢查取消狀態(tài)。比如询微,如果在調(diào)用start
方法之前取消了一個(gè)操作崖瞭,start
方法將退出而不啟動(dòng)該任務(wù)。
在任何自定義代碼中撑毛,都應(yīng)該始終支持取消語(yǔ)義书聚。特別的,主要任務(wù)的代碼應(yīng)該定期性的檢查cancelled
屬性的值藻雌。如果為YES雌续,operation對(duì)象應(yīng)該盡可能快的清理并退出。如果實(shí)現(xiàn)了自定義的start
方法蹦疑,那么該方法應(yīng)該適當(dāng)?shù)奶崆皺z查取消狀態(tài)西雀。
除了當(dāng)操作取消時(shí)退出操作,將取消的操作設(shè)置為一個(gè)合適的最終狀態(tài)也是很重要的歉摧。如果我們自己管理finished
和executing
屬性的值(可能是因?yàn)檎趫?zhí)行并發(fā)操作), 必須相應(yīng)地更新這些屬性艇肴。特別的腔呜,必須將finished
屬性的值返回為YES,executing
屬性的值為NO再悼。即使操作在開(kāi)始執(zhí)行之前就被取消也必須進(jìn)行這些更改核畴。
幾個(gè)方法的簡(jiǎn)單介紹
執(zhí)行操作的方法
-
- (void)start;
開(kāi)始執(zhí)行操作。 該方法的默認(rèn)實(shí)現(xiàn)會(huì)更改operation的執(zhí)行狀態(tài)冲九,并調(diào)用接受者的main
方法谤草。 該方法還會(huì)執(zhí)行若干項(xiàng)檢查確保操作能夠?qū)嶋H運(yùn)行。比如莺奸,如果receiver被取消或者已經(jīng)finished丑孩,該方法將不會(huì)調(diào)用main
方法而直接return。如果操作正在執(zhí)行或者尚未準(zhǔn)備執(zhí)行灭贷,該方法或拋出 NSInvalidArgumentException 異常温学。注意:
如果一個(gè)操作依賴的其他操作沒(méi)有finished,則該認(rèn)為該操作還沒(méi)有準(zhǔn)備好執(zhí)行如果實(shí)現(xiàn)了并發(fā)操作甚疟,必須覆蓋
start
方法仗岖,并使用該方法開(kāi)啟操作。該方法自定義的實(shí)現(xiàn)在任何時(shí)候都不應(yīng)該調(diào)用 super览妖。 除了為你的任務(wù)配置執(zhí)行環(huán)境轧拄,該方法的自定義實(shí)現(xiàn)也必須跟蹤operation 的狀態(tài)并提供適當(dāng)?shù)臓顟B(tài)轉(zhuǎn)變。當(dāng)操作執(zhí)行并完成它的工作之后讽膏,還應(yīng)該分別為isExecuting
和isFinished
路徑生成KVO通知檩电。如果想要手動(dòng)執(zhí)行操作的話可以顯式的調(diào)用該方法。但是桅打,對(duì)一個(gè)已經(jīng)在操作隊(duì)列里operation對(duì)象調(diào)用該方法是嗜,或者在調(diào)用該方法之后對(duì)操作進(jìn)行排隊(duì),都是編程錯(cuò)誤挺尾。一旦將operation添加到隊(duì)列,隊(duì)列將負(fù)責(zé)管理操作
-
- (void)main;
執(zhí)行receiver的非并發(fā)任務(wù)站绪。該方法的默認(rèn)實(shí)現(xiàn)是實(shí)際上什么都沒(méi)做遭铺。我們應(yīng)該覆蓋該方法來(lái)執(zhí)行所需的任務(wù)。在自定義實(shí)現(xiàn)中恢准,不應(yīng)該調(diào)用super魂挂。該方法將會(huì)在NSOperation
提供的 autorelease pool 中自動(dòng)執(zhí)行,所以不需要我們創(chuàng)建 autorelease pool馁筐。如果要實(shí)現(xiàn)并發(fā)操作涂召,不需要覆蓋該方法。但是如果從自定義的
start
方法調(diào)用的話可能就需要重寫該方法了 -
@property(copy) void (^completionBlock)(void);
操作主要任務(wù)完成之后執(zhí)行的block敏沉。每當(dāng)一個(gè)NSOperation執(zhí)行完畢果正,它就會(huì)調(diào)用它的completionBlock屬性一次炎码。 該block的執(zhí)行上下文并不確定,但通常是在子線程中秋泳。因此潦闲,不應(yīng)該使用該block執(zhí)行任何需要在特定執(zhí)行上下文的工作。相反迫皱,應(yīng)該該工作分配給主線程或者能夠處理該任務(wù)的特定線程中歉闰。
當(dāng)
finished
屬性值為YES時(shí),該block將執(zhí)行卓起。因?yàn)閎lock在operation完成其任務(wù)后執(zhí)行和敬,所以不能使用該block來(lái)排隊(duì)等待被認(rèn)為是該任務(wù)一部分的其他任務(wù)。finished
屬性為YES的operation對(duì)象必須完成它所有的任務(wù)戏阅。該block應(yīng)該通知相應(yīng)的對(duì)象工作已經(jīng)完成昼弟,或者執(zhí)行其他的一些任務(wù)(與operation實(shí)際任務(wù)相關(guān),但不屬于操作的一部分)在iOS 8以后和 macOS 10.10以后饲握,在該block執(zhí)行之后將該屬性置為nil.
取消操作的方法
-
- (void)cancel;
通知operation對(duì)象停止執(zhí)行其任務(wù)私杜。該方法不會(huì)強(qiáng)制停止operation的代碼。相反的救欧,它更新對(duì)象的內(nèi)部標(biāo)志來(lái)反應(yīng)狀態(tài)的變化衰粹。如果操作已經(jīng)finished,該方法將不會(huì)起作用笆怠。取消一個(gè)在操作隊(duì)列中铝耻,但還沒(méi)有開(kāi)始執(zhí)行的operation,可以更快地從隊(duì)列中移除操作蹬刷。
屬性
-
@property(readonly, getter=isCancelled) BOOL cancelled;
指示操作是否已經(jīng)取消的布爾值瓢捉。
默認(rèn)是NO,調(diào)用
cancel
方法將該屬性設(shè)為YES办成。 一旦取消泡态,operation必須轉(zhuǎn)至finished狀態(tài)。取消一個(gè)operation不會(huì)直接停止receiver代碼的執(zhí)行迂卢。如果返回YES某弦,operation對(duì)象負(fù)責(zé)定期地調(diào)用該方法并自行停止。
在執(zhí)行operation的任務(wù)之前而克,應(yīng)該檢查該屬性的值靶壮。通常是在自定義的
main
方法中的開(kāi)頭處檢查。在開(kāi)始執(zhí)行操作或者在執(zhí)行的任意時(shí)候员萍,操作都可能被取消腾降。因此,在main
方法的開(kāi)頭檢查該屬性的值(并在該方法中定期的檢查)碎绎,可以在操作取消時(shí)盡可能快的退出螃壤。 -
@property(readonly, getter=isExecuting) BOOL executing;
指示操作是否正在執(zhí)行的布爾值抗果。
如果operation正在執(zhí)行它的主任務(wù),屬性值為YES映穗,否則為NO窖张。
當(dāng)實(shí)現(xiàn)了一個(gè)并發(fā)操作對(duì)象,必須覆蓋該屬性的實(shí)現(xiàn)蚁滋,以便于可以返回操作對(duì)象的執(zhí)行狀態(tài)宿接。在自定義的實(shí)現(xiàn)中链快,當(dāng)操作對(duì)象的執(zhí)行狀態(tài)改變的時(shí)候必須為
isExecuting
路徑生成KVO通知對(duì)于非并發(fā)操作不需要重新實(shí)現(xiàn)該屬性
-
@property(readonly, getter=isFinished) BOOL finished;
指示操作是否已完成其任務(wù)忱叭。
如果operation已經(jīng)完成它的主任務(wù),該屬性值為YES. 如果正在執(zhí)行或還沒(méi)有開(kāi)始執(zhí)行則為NO
當(dāng)實(shí)現(xiàn)一個(gè)并發(fā)操作時(shí)累魔,必須重寫該屬性的實(shí)現(xiàn)走诞,以便返回operation的完成狀態(tài)副女。在自定義實(shí)現(xiàn)中,如果操作的finished狀態(tài)改變的話蚣旱,必須為
isFinished
路徑生成KVO通知碑幅。對(duì)于非并發(fā)操作無(wú)需重寫該屬性的實(shí)現(xiàn)
-
`@property(readonly, getter=isAsynchronous) BOOL asynchronous;
指示操作是否異步執(zhí)行其任務(wù)。
對(duì)于當(dāng)前線程異步執(zhí)行的操作塞绿,該屬性值為YES沟涨。對(duì)于當(dāng)前線程同步執(zhí)行的操作為NO。默認(rèn)為NO
當(dāng)實(shí)現(xiàn)一個(gè)異步操作對(duì)象异吻,必須實(shí)現(xiàn)該屬性并返回YES
-
@property(readonly, getter=isReady) BOOL ready;
指示現(xiàn)在是否可以執(zhí)行操作的布爾值
操作的準(zhǔn)備情況取決于它們對(duì)其他操作的依賴裹赴,以及你定義的自定義的條件。
NSOperation
類管理對(duì)其他操作的依賴關(guān)系诀浪,并根據(jù)這些依賴關(guān)系報(bào)告receiver的準(zhǔn)備情況棋返。如果想使用自定義條件來(lái)定義操作對(duì)象的準(zhǔn)備情況,需要重寫該屬性的實(shí)現(xiàn)雷猪,并返回一個(gè)準(zhǔn)確反映receiver的準(zhǔn)備情況的值睛竣。如果這樣做,自定義的實(shí)現(xiàn)必須從super獲取默認(rèn)的屬性值求摇,并將該值和冰島該屬性的新值中酵颁。在自定義實(shí)現(xiàn)中,當(dāng)操作對(duì)象的準(zhǔn)備狀態(tài)改變的時(shí)候月帝,必須為
isReady
路徑生成KVO通知 -
@property(copy) NSString *name;
operation的名稱。 為操作對(duì)象分配一個(gè)名稱幽污,方便debug嚷辅。
管理依賴
-
- (void)addDependency:(NSOperation *)op;
使receiver依賴于指定操作的完成
參數(shù):
operation: receiver應(yīng)該依賴的操作。不應(yīng)該向receiver重復(fù)添加相同的依賴距误,這樣做的結(jié)果是undefined直到依賴的所有操作都執(zhí)行結(jié)束后簸搞,receiver才會(huì)被認(rèn)為準(zhǔn)備好執(zhí)行扁位。如果receiver已經(jīng)在執(zhí)行其任務(wù),添加依賴將不會(huì)有效果趁俊。該方法可能會(huì)改變r(jià)eceiver的
isReady
和dependencies
屬性域仇。注意不要造成循環(huán)依賴。這樣做的話會(huì)造成操作間的死鎖寺擂,并可能會(huì)freeze你的程序暇务。
-
- (void)removeDependency:(NSOperation *)op;
移除receiver對(duì)特定操作的依賴。
該方法可能會(huì)更改receiver的
isReady
和dependencies
屬性怔软。 -
@property(readonly, copy) NSArray<NSOperation *> *dependencies;
在當(dāng)前對(duì)象開(kāi)始執(zhí)行之前必須完成執(zhí)行的操作對(duì)象數(shù)組垦细。
該屬性是包含的
NSOperation
對(duì)象的數(shù)組。使用addDependency:
方法為該數(shù)組添加對(duì)象挡逼。直到依賴的操作對(duì)象都執(zhí)行結(jié)束后括改,operation才可以執(zhí)行。操作完成執(zhí)行時(shí)也不會(huì)從該列表中移除家坎≈瞿埽可以使用該列表跟蹤所有的依賴操作,包括那些已經(jīng)完成的操作虱疏。唯一能從該列表中移除operation的方法是調(diào)用
removeDependency:
方法惹骂。
NSBlockOperation
NSBlockOperation類是NSOperation的一個(gè)具體子類,用于管理一個(gè)或多個(gè)block的并發(fā)執(zhí)行订框∥錾唬可以使用該對(duì)象一次執(zhí)行數(shù)個(gè)block,而不必為每個(gè)block創(chuàng)建單獨(dú)的操作對(duì)象穿扳。當(dāng)執(zhí)行多個(gè)block時(shí)衩侥,只有當(dāng)所有的block執(zhí)行結(jié)束之后,該操作對(duì)象才會(huì)被視為finished矛物。
添加到NSBlockOperation的block以默認(rèn)優(yōu)先級(jí)調(diào)度到適當(dāng)?shù)墓ぷ麝?duì)列茫死。block本身不應(yīng)該對(duì)其執(zhí)行環(huán)境做任何假設(shè)
方法介紹
-
+ (instancetype)blockOperationWithBlock:(void (^)(void))block;
創(chuàng)建并返回一個(gè)NSBlockOperation對(duì)象,并為其添加指定的block履羞。
-
- (void)addExecutionBlock:(void (^)(void))block;
添加指定block到receiver要執(zhí)行的的block列表中峦萎。
指定的block不應(yīng)該對(duì)它的執(zhí)行環(huán)境做任何假設(shè)。
當(dāng)receiver正在執(zhí)行或者已經(jīng)finished時(shí)調(diào)用該方法會(huì)拋出
NSInvalidArgumentException
異常 -
@property(readonly, copy) NSArray<void (^)(void)> *executionBlocks;
與receiver相關(guān)聯(lián)的block數(shù)組
該數(shù)組中的block是調(diào)用
addExecutionBlock:
方法添加的block的副本忆首。
NSInvocationOperation
NSInvocationOperation類是NSOperation的一個(gè)具體子類爱榔,用于開(kāi)啟一個(gè)操作,該操作包括在指定對(duì)象上調(diào)用一個(gè)selector糙及。
方法
-
- (instancetype)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
參數(shù):
target: 定義指定selector的對(duì)象详幽。
sel: 運(yùn)行該操作對(duì)象時(shí)會(huì)調(diào)用該selector。selector可能會(huì)有0或1個(gè)參數(shù)。如果有參數(shù)唇聘,參數(shù)的類型必須是 id版姑。 方法的返回類型可以是 void、基本數(shù)據(jù)類型迟郎,或是可以作為id類型返回的對(duì)象剥险。
arg: 傳遞給selector的參數(shù)對(duì)象。如果selector不需要參數(shù)宪肖,將arg置為nil即可表制。
該方法返回一個(gè) NSInvocationOperation對(duì)象,或者nil(如果target對(duì)象沒(méi)有實(shí)現(xiàn)指定的selector)
如果selector的返回類型是 非void,我們可以在操作完成執(zhí)行后調(diào)用
result
方法來(lái)獲取返回值匈庭。 -
- (instancetype)initWithInvocation:(NSInvocation *)inv;
使用指定的NSInvocation對(duì)象初始化一個(gè)NSInvocationOperation對(duì)象夫凸。
返回一個(gè)NSInvocationOperation對(duì)象或者nil(如果對(duì)象不能被初始化)
-
@property(readonly, retain) id result;
invocation 或方法的結(jié)果。
該方法返回的對(duì)象或者返回值的NSValue對(duì)象(如果返回值不是對(duì)象會(huì)轉(zhuǎn)成NSValue對(duì)象)阱持。如果方法或者invocation未完成執(zhí)行夭拌,則為nil。
如果在執(zhí)行方法或調(diào)用期間發(fā)生異常衷咽,訪問(wèn)該屬性將會(huì)再次引發(fā)該異常鸽扁。如果操作被取消或者invocation或方法返回類型為void,訪問(wèn)該屬性也會(huì)引發(fā)異常镶骗。
NSOperation與GCD
盡管GCD對(duì)于內(nèi)嵌異步操作十分理想桶现,NSOperation依舊提供更復(fù)雜、面向?qū)ο蟮挠?jì)算模型鼎姊,它對(duì)于涉及到各種類型數(shù)據(jù)骡和、需要重復(fù)處理的任務(wù)是更加理想的
什么時(shí)候使用GCD
Dispatch queues, groups, semaphores(信號(hào)量), sources, 和 barriers 組成了一組基本的并發(fā)基元,其上構(gòu)建了所有的系統(tǒng)框架相寇。
對(duì)于一次性的計(jì)算或簡(jiǎn)單的加速現(xiàn)有方法慰于,使用輕量級(jí)的GCD比使用NSOperation更方便。
什么時(shí)候使用NSOperation
NSOperation 可以按照特定的隊(duì)列優(yōu)先級(jí)和服務(wù)質(zhì)量(qualityOfService
)來(lái)調(diào)度一組依賴關(guān)系唤衫。與在GCD隊(duì)列中的block不同婆赠, NSOperation可以被取消,以及查詢其操作狀態(tài)佳励。通過(guò)繼承休里,NSOperation可以將其工作結(jié)果與自身關(guān)聯(lián)起來(lái),供將來(lái)參考赃承。
資料來(lái)源:
- 另外推薦一篇 Mattt大神的一篇文章:NSOperation妙黍,中文翻譯請(qǐng)戳這里