塊與大中樞派發(fā)
“塊”(block)是一種可在C帆赢、C++及Objective-C代碼中使用的“詞法閉包”(lexical closure)碟狞,它極為有用,開發(fā)者可將代碼像對象一樣傳遞,令其在不同環(huán)境(context)下運行。在定義“塊”的范圍內(nèi)助析,它可以訪問到其中的全部變量。
“大中樞派發(fā)”(Grand Central Dispatch椅您,GCD)是一種與塊有關(guān)的技術(shù),它提供了對線程的抽象寡键,而這種抽象則基于“派發(fā)隊列”(dispatch queue)掀泳。開發(fā)者可將塊排入隊列中雪隧,由GCD負(fù)責(zé)處理所有調(diào)度事宜。
37.理解“塊”這一概念
塊是C员舵、C++脑沿、Objective-C中的詞法閉包。
塊可接受參數(shù)马僻,也可返回值庄拇。
塊可以分配在棧或堆上韭邓,也可以是全局的措近。分配在棧上的塊可拷貝到堆里,這樣的話女淑,就和標(biāo)準(zhǔn)的Objective-C對象一樣瞭郑,具備引用計數(shù)了。
38.為常用的塊類型創(chuàng)建typedef
以typedef重新定義塊類型,可令塊變量用起來更加簡單。
定義新類型時應(yīng)遵從現(xiàn)有的命名習(xí)慣荷科,勿使其名稱與別的類型相沖突手负。
不妨為同一個塊簽名定義多個類型別名。如果要重構(gòu)的代碼使用了塊類型的某個別名粉臊,那么只需修改相應(yīng)typedef中的塊簽名即可,無需改動其他typedef。
39.用handler塊降低代碼分散程度
在創(chuàng)建對象時场绿,可以使用內(nèi)聯(lián)的handler塊將相關(guān)業(yè)務(wù)邏輯一并聲明。
在有多個實例需要監(jiān)控時俺夕,如果采用委托模式裳凸,那么經(jīng)常需要根據(jù)傳入的對象來切換,而若改用handler塊來實現(xiàn)劝贸,則可直接將塊與相關(guān)對象放在一起姨谷。
設(shè)計API時如果用到了handler塊,那么可以增加一個參數(shù)映九,使調(diào)用者可通過此參數(shù)來決定應(yīng)該把塊安排在哪個隊列上執(zhí)行梦湘。
40.用塊引用其所屬對象時不要出現(xiàn)保留環(huán)
如果塊所捕獲的對象直接或間接地保留了塊本身,那么就得當(dāng)心保留環(huán)問題件甥。
一定要找個適當(dāng)?shù)臅r機解除保留環(huán)捌议,而不能把責(zé)任推給API的調(diào)用者。
41.多用派發(fā)隊列引有,少用同步鎖
派發(fā)隊列可用來表述同步語義(synchronization semantic)瓣颅,這種做法要比使用@synchronized塊或NSLock對象更簡單。
將同步與異步派發(fā)結(jié)合起來譬正」梗可以實現(xiàn)與普通加鎖機制一樣的同步行為檬姥,而這么做卻不會阻塞執(zhí)行異步派發(fā)的線程。
使用同步隊列及柵欄塊粉怕,可以令同步行為更加高效健民。
42.多用GCD,少用performSelector系列方法
performSelector系列方法在內(nèi)存管理方面容易有疏失贫贝。它無法確定將要執(zhí)行的選擇子具體是什么秉犹,因而ARC編譯器也就無法插入適當(dāng)?shù)膬?nèi)存管理方法。
performSelector系列方法所能處理得選擇子太過局限了稚晚,選擇子的返回值類型及發(fā)送給方法的參數(shù)個數(shù)都受到限制崇堵。
如果想把任務(wù)放在另一個線程上執(zhí)行,那么最好不要用performSelector系列方法蜈彼,而是應(yīng)該把任務(wù)封裝到塊里筑辨,然后調(diào)用大中樞派發(fā)機制的相關(guān)方法來實現(xiàn)。
43.掌握GCD及操作隊列的使用時機
使用NSOperation及NSOperationQueue的好處:
- 取消某個操作
- 指定操作間的依賴關(guān)系幸逆。
- 通過鍵值觀測機制(KVO)來監(jiān)聽棍辕。
- 指定操作的優(yōu)先級。
- 重用NSOperation對象还绘。
44.通過Dispatch Group機制楚昭,根據(jù)系統(tǒng)資源狀況來執(zhí)行任務(wù)
一系列任務(wù)可歸入一個dispatch group之中,開發(fā)者可以在這組任務(wù)執(zhí)行完畢時獲得通知拍顷。
通過dispatch group抚太,可以在并發(fā)隊列里同時執(zhí)行多項任務(wù)。
45.使用dispatch_once來執(zhí)行只需運行一次的線程安全代碼
經(jīng)常需要編寫“只需執(zhí)行一次的線程安全代碼”(thread-safe single-code execution)昔案。通過GCD所提供的dispatch_once函數(shù)尿贫,很容易就能實現(xiàn)此功能。
標(biāo)記應(yīng)該聲明在static過global作用域中踏揣,這樣的話庆亡,在把只需執(zhí)行一次的塊傳給dispatch_once函數(shù)時,傳進(jìn)去的標(biāo)記也是相同的捞稿。
46.不要使用dispatch_get_current_queue
dispatch_get_current_queue函數(shù)的行為常常與開發(fā)者所預(yù)期的不同又谋。此函數(shù)已經(jīng)廢棄,只應(yīng)做調(diào)試之用娱局。
由于派發(fā)隊列是按層級來組織的彰亥,所以無法單用某個隊列隊象來描述“當(dāng)前隊列”這一概念。
dispatch_get_current_queue函數(shù)用于解決由不可重入的代碼所引發(fā)的死鎖衰齐,然而能用此函數(shù)解決的問題任斋,通常也能改用“隊列特定數(shù)據(jù)”來解決。