NSOperation的簡(jiǎn)單介紹

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ì)象必須為isExecutingisFinished路徑生成KVO通知爷耀,標(biāo)記操作狀態(tài)的最終更改甘桑。(在取消的情況下,即使操作沒(méi)有結(jié)束它的任務(wù)歹叮,也要更新isFinished跑杭。 排隊(duì)的操作在從隊(duì)列中刪除之前必須是已經(jīng)finished)。除了生成KVO通知咆耿,重寫的executingfinished屬性也應(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)也是很重要的歉摧。如果我們自己管理finishedexecuting屬性的值(可能是因?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)該分別為isExecutingisFinished路徑生成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的isReadydependencies屬性域仇。

    注意不要造成循環(huán)依賴。這樣做的話會(huì)造成操作間的死鎖寺擂,并可能會(huì)freeze你的程序暇务。

  • - (void)removeDependency:(NSOperation *)op;

    移除receiver對(duì)特定操作的依賴。

    該方法可能會(huì)更改receiver的isReadydependencies屬性怔软。

  • @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)源:
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瞧剖,隨后出現(xiàn)的幾起案子废境,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件噩凹,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡毡咏,警方通過(guò)查閱死者的電腦和手機(jī)驮宴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)呕缭,“玉大人堵泽,你說(shuō)我怎么就攤上這事』肿埽” “怎么了迎罗?”我有些...
    開(kāi)封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)片仿。 經(jīng)常有香客問(wèn)我纹安,道長(zhǎng),這世上最難降的妖魔是什么砂豌? 我笑而不...
    開(kāi)封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任厢岂,我火速辦了婚禮,結(jié)果婚禮上阳距,老公的妹妹穿的比我還像新娘塔粒。我一直安慰自己,他們只是感情好筐摘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布卒茬。 她就那樣靜靜地躺著,像睡著了一般咖熟。 火紅的嫁衣襯著肌膚如雪圃酵。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天球恤,我揣著相機(jī)與錄音辜昵,去河邊找鬼。 笑死咽斧,一個(gè)胖子當(dāng)著我的面吹牛堪置,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播张惹,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼舀锨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了宛逗?” 一聲冷哼從身側(cè)響起坎匿,我...
    開(kāi)封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后替蔬,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體告私,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年承桥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了驻粟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凶异,死狀恐怖蜀撑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情剩彬,我是刑警寧澤酷麦,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站喉恋,受9級(jí)特大地震影響沃饶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瀑晒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一绍坝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧苔悦,春花似錦轩褐、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蟋座,卻和暖如春拗踢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背向臀。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工巢墅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人券膀。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓君纫,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親芹彬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蓄髓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容