NSOperation的高級(jí)用法

嘮嗑

最近開始遷移文章读恃,把以前寫的一些文章都遷移到簡(jiǎn)書,也算開始在簡(jiǎn)書安家了舔亭。

前言

本文是對(duì)([WWDC 2015 Session 226: Advanced NSOperations]) 的一個(gè)小結(jié)蹋艺,在這個(gè)視頻中介紹了用NSOperation來組織App中的功能結(jié)構(gòu),使邏輯更清晰剥悟。如果沒有看過這個(gè)視頻可以看看視頻灵寺,有助于加深對(duì)operation的理解。這篇文章更多的是一些理論知識(shí)区岗,沒什么代碼略板,但是理解一些內(nèi)部原理有助于平時(shí)我們?nèi)タ吹谌綆欤热?SDWebImage AFNetworking YYImage等里面對(duì)operation自定義的運(yùn)用慈缔。

1.NSOperation 和NSOperationQueue簡(jiǎn)介

NSOperationQueue是高級(jí)的dispatch_queue_t叮称,但同時(shí)也提供了一些功能特性供開發(fā)者使用。

1.cancelAllOperations:可以取消隊(duì)列中所有還未執(zhí)行的operation
2.maxConcurrentOperationCount:最大并行并發(fā)數(shù)

我們來看一張圖

image

如果我們?cè)O(shè)置maxConcurrentOperationCount=2藐鹤,我們可以將其看成一個(gè)并行隊(duì)列瓤檐,同一時(shí)刻允許最大的并發(fā)數(shù)為2。只有上一個(gè)operation做完后娱节,下一個(gè)operation才會(huì)開始挠蛉。maxConcurrentOperationCount的默認(rèn)值為default,意思是系統(tǒng)會(huì)開設(shè)適當(dāng)數(shù)量的子線程肄满。

NSOperation的特點(diǎn)

  1. 可以cancel未執(zhí)行的operation
  2. 指定相同或者不同隊(duì)列的依賴關(guān)系
  3. kvo監(jiān)控NSOperation的對(duì)象屬性
  4. 指定操作優(yōu)先級(jí)
  5. 重用operation:operation只能被執(zhí)行一次后生命周期就結(jié)束了谴古,不能被多次執(zhí)行。

NSOperation可以看成dispatch_block_t的封裝稠歉。我們來看看operation 的生命周期(圖1)掰担,當(dāng)我們init一個(gè)operation,它的初始狀態(tài)是Pending怒炸,然后在某一時(shí)刻會(huì)到Ready恩敌,這時(shí)operation從queue中拿出開始執(zhí),進(jìn)入executing狀態(tài)横媚,最后執(zhí)行完畢到finished狀態(tài)。在除finished以外的其它三個(gè)狀態(tài)都可以到cancelled狀態(tài)月趟。

圖1

operation各個(gè)狀態(tài)說明:

Ready:一個(gè)operation只有在Ready狀態(tài)才可以被queue執(zhí)行灯蝴。下圖,在一個(gè)串行的queue中孝宗,即使第一次進(jìn)入Ready狀態(tài)的operation是在第四個(gè)被放進(jìn)去的穷躁,但是還是第一個(gè)執(zhí)行。這樣的好處就是因妇,放入串行隊(duì)列的operation我們不需要在operation定義的時(shí)候就確定它的執(zhí)行順序问潭,而是在后面動(dòng)態(tài)的確定執(zhí)行順序。(控制進(jìn)入Ready狀態(tài)的時(shí)機(jī))

image

用這個(gè)Ready屬性我們可以做什么事兒呢婚被?我們可以確定依賴(dependencies)狡忙。默認(rèn)條件下,如果A依賴于B址芯,當(dāng)A進(jìn)入finish狀態(tài)灾茁,那么B才會(huì)進(jìn)入Ready狀態(tài)窜觉。這個(gè)依賴可以存在于不同的operationQueue。一個(gè)operaion直有它依賴的所有operation處于finish狀態(tài)北专,它才回進(jìn)入ready狀態(tài)禀挫。如果我們用queue來管理operation,operation在加入到queue中的某一個(gè)時(shí)刻拓颓,它會(huì)在它依賴的operaions執(zhí)行完畢(或者我們沒有設(shè)置依賴)语婴,在某一個(gè)時(shí)刻自動(dòng)進(jìn)入Ready狀態(tài)并被執(zhí)行。當(dāng)然我們可以手動(dòng)執(zhí)行operation驶睦,但是官方不推薦砰左,因?yàn)檎{(diào)用一個(gè)未Ready狀態(tài)的operation會(huì)導(dǎo)致異常拋出。

Cancel:可以cancel未執(zhí)行的operation啥繁,該方法會(huì)設(shè)置對(duì)象內(nèi)的標(biāo)志位菜职,表明operation不需要執(zhí)行,如果operation已經(jīng)start旗闽,就不能取消了酬核。operation進(jìn)入cancel狀態(tài)只是一個(gè)Bool值的翻轉(zhuǎn),當(dāng)我們繼承operation适室,我們要自己決定cancel時(shí)候需要做什么業(yè)務(wù)嫡意。比如我們?cè)趫?zhí)行一個(gè)網(wǎng)絡(luò)請(qǐng)求,cancel狀態(tài)代表著cancel 一個(gè)urlSession捣辆。當(dāng)我們請(qǐng)求一個(gè)數(shù)據(jù)庫蔬螟,cancel代表我們停止對(duì)數(shù)據(jù)庫進(jìn)行讀寫操作。所以我們最好KVO這個(gè)屬性汽畴,然后做適當(dāng)?shù)倪壿嬀山怼<尤氲絨ueue的operaion如果不處于finish狀態(tài),可以進(jìn)入cancel狀態(tài)忍些。調(diào)用[operaion cancel]鲁猩。默認(rèn)條件下,operation調(diào)用cancel罢坝,也會(huì)標(biāo)志它進(jìn)入finished狀態(tài)廓握。因?yàn)橹挥羞@樣依賴它的operation才有機(jī)會(huì)被執(zhí)行。如果我們自定義operation嘁酿,我們要考慮它進(jìn)入cancel狀態(tài)或者這個(gè)operation沒有被成功執(zhí)行時(shí)候隙券,根據(jù)業(yè)務(wù)是否應(yīng)該讓它進(jìn)入finished。

KVO:operation 的狀態(tài)是滿足KVO的闹司,可以被監(jiān)聽娱仔,可以被監(jiān)聽的keyPath(isCancelled,isAsynchronous,isExecuting,isFinished,isReady等)。注意:因?yàn)閛peraion可能在任何線程內(nèi)被執(zhí)行开仰,如果我們將UI元素和以上屬性做綁定拟枚,那么KVO過來的行為就可能發(fā)生在任何的線程內(nèi)薪铜。保險(xiǎn)的做法是:如果KVO得知通知后要做UI的事情,都扔到主線程中做恩溅。如果我們?cè)谧远xoperaion時(shí)候重寫以上屬性隔箍,也要確保它們可以被KVO和KVC。

線程安全:系統(tǒng)提供的operaion的子類都是線程安全的脚乡,所有用系統(tǒng)的operation我們不需要加鎖蜒滩,當(dāng)我們自定義operaion,提供一些對(duì)外的數(shù)據(jù)存取的方法自己加鎖奶稠。

同步和異步的Operaions:

如果我們手動(dòng)執(zhí)行一個(gè)operation俯艰,而不是把它放入一個(gè)operationQueue進(jìn)行管理。operation自己本身也有同步和異步之分锌订,(默認(rèn)同步)竹握。同步的operation不會(huì)開子線程,會(huì)在調(diào)用start這個(gè)方法的線程內(nèi)執(zhí)行辆飘。而異步的會(huì)自己開啟子線程啦辐,如果我們用queue來管理operaion,我們希望它是同步的蜈项,因?yàn)閝ueue自己會(huì)開子線程芹关,我們只要保證加入queue的operation可以按次序執(zhí)行就行。

如果我們不想用queue和GCD來管理operation但想要利用子線程執(zhí)行operation紧卒,我們應(yīng)該自定義一個(gè)異步的operation侥衬。我們需要追蹤operation的狀態(tài)而且手動(dòng)觸發(fā)KVO∨芊迹或者用KVC觸發(fā)KVO轴总。其實(shí)我們平時(shí)在用點(diǎn)語法用系統(tǒng)的setter的時(shí)候,它是通過KVC設(shè)置的博个,所以自動(dòng)會(huì)觸發(fā)KVO通知肘习,如果我們重載了setter,為了讓屬性符合KVO條件坡倔,必須手動(dòng)觸發(fā)通知。

image

作為抽象類脖含,我們可以繼承NSOpration罪塔,實(shí)現(xiàn)自己的operation來代碼業(yè)務(wù)邏輯。

同步的operation條件:

1.重載main方法养葵,這個(gè)方法里面放主業(yè)務(wù)邏輯征堪。也需要查看cancel屬性

2.如果我們重載了getter和setter,必須確保調(diào)用是線程安全的关拒。

異步operation條件:

1.重載start方法佃蚜,和asynchronous庸娱,exciting,finished屬性

start方法中我們必須確保operation異步執(zhí)行谐算,在此方法中我們需要改變executing更新狀態(tài)熟尉,發(fā)送executing KVO通知。當(dāng)結(jié)束operation洲脂。必須更新isExecuting和isFinished狀態(tài)斤儿,并觸發(fā)kvo通知。當(dāng)cancel一個(gè)operation時(shí)候恐锦,我們也要更新isFinished狀態(tài)往果,即使此時(shí)operation還未執(zhí)行。在queue 中的operation必須進(jìn)入cancel狀態(tài)后才可以被從operation中移除一铅,

注意:start里面不能調(diào)用[super start];在自定義異步operation中陕贮,我們完全自定義start,已經(jīng)全部模擬了父類默認(rèn)的start行為(start task && send KVO)潘飘,在start方法里面肮之,我們還要查看isCanceled屬性,確保start task前福也,task是不是已經(jīng)被取消局骤。如果我們自定義了dependency,我們還需要發(fā)送isReady的KVO通知暴凑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末峦甩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子现喳,更是在濱河造成了極大的恐慌凯傲,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗦篱,死亡現(xiàn)場(chǎng)離奇詭異冰单,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)灸促,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門诫欠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人浴栽,你說我怎么就攤上這事荒叼。” “怎么了典鸡?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵被廓,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我萝玷,道長(zhǎng)嫁乘,這世上最難降的妖魔是什么昆婿? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮蜓斧,結(jié)果婚禮上仓蛆,老公的妹妹穿的比我還像新娘。我一直安慰自己法精,他們只是感情好多律,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著搂蜓,像睡著了一般狼荞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上帮碰,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天相味,我揣著相機(jī)與錄音,去河邊找鬼殉挽。 笑死丰涉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的斯碌。 我是一名探鬼主播一死,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼傻唾!你這毒婦竟也來了投慈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤冠骄,失蹤者是張志新(化名)和其女友劉穎伪煤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凛辣,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抱既,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扁誓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片防泵。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蝗敢,靈堂內(nèi)的尸體忽然破棺而出择克,到底是詐尸還是另有隱情,我是刑警寧澤前普,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站壹堰,受9級(jí)特大地震影響拭卿,放射性物質(zhì)發(fā)生泄漏骡湖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一峻厚、第九天 我趴在偏房一處隱蔽的房頂上張望响蕴。 院中可真熱鬧,春花似錦惠桃、人聲如沸浦夷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽劈狐。三九已至,卻和暖如春呐馆,著一層夾襖步出監(jiān)牢的瞬間肥缔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工汹来, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留续膳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓收班,卻偏偏與公主長(zhǎng)得像坟岔,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子摔桦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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