iOS 編寫高質(zhì)量Objective-C代碼(七)—— GCD專欄

《編寫高質(zhì)量OC代碼》已順利完成一二三四五六七八篇艾船!
附上鏈接:
iOS 編寫高質(zhì)量Objective-C代碼(一)—— 簡(jiǎn)介
iOS 編寫高質(zhì)量Objective-C代碼(二)—— 面向?qū)ο?/a>
iOS 編寫高質(zhì)量Objective-C代碼(三)—— 接口和API設(shè)計(jì)
iOS 編寫高質(zhì)量Objective-C代碼(四)—— 協(xié)議與分類
iOS 編寫高質(zhì)量Objective-C代碼(五)—— 內(nèi)存管理機(jī)制
iOS 編寫高質(zhì)量Objective-C代碼(六)—— block專欄
iOS 編寫高質(zhì)量Objective-C代碼(七)—— GCD專欄
iOS 編寫高質(zhì)量Objective-C代碼(八)—— 系統(tǒng)框架


本篇的主題是iOS中的 “ 大中樞開(kāi)發(fā) GCD ”

先簡(jiǎn)單介紹一下今天的主角:GCD

  • GCD(Grand Central Dispatch):一種與塊相關(guān)的技術(shù)耻卡,提供了對(duì)線程的抽象管理(基于派發(fā)隊(duì)列dispatch queue)跟磨。GCD會(huì)根據(jù)系統(tǒng)資源情況暇榴,適時(shí)且高效地 “創(chuàng)建線程” 蟀淮、“復(fù)用線程” 蚪腐、 “銷毀線程”宝踪。

一侨糟、多用派發(fā)隊(duì)列,少用同步鎖

問(wèn):在iOS開(kāi)發(fā)中瘩燥,如何通過(guò)鎖來(lái)提供同步機(jī)制秕重?(以前面試中,經(jīng)常問(wèn)道的問(wèn)題..)

答:在GCD出現(xiàn)之前厉膀,有兩種方式:

  • 同步塊:@synchronized(self) {...}
- (void)synchronizedMethod {
    
    @synchronized (self) {
        
        // Safe area...
    }
}
  • NSLock:[_lock lock]; & [_lock unlock];
_lock = [[NSLock alloc] init];

- (void)synchronizedMethod {
    
    [_lock lock];    
    // Safe area..    
    [_lock unlock];
}

不過(guò)這兩種寫法效率很低溶耘,如果有很多屬性二拐,那么每個(gè)屬性的同步塊都要等其他同步塊執(zhí)行完畢才能執(zhí)行。

GCD出現(xiàn)后凳兵,GCD與Block相結(jié)合百新,使開(kāi)發(fā)變得更加簡(jiǎn)單、高效庐扫。

問(wèn):如何保證屬性讀寫時(shí)線程絕對(duì)安全饭望?
答:在屬性寫入時(shí),使用柵欄塊barrier形庭。只有當(dāng)前所有并發(fā)塊都執(zhí)行完畢后铅辞,才會(huì)執(zhí)行barrier塊,然后才會(huì)繼續(xù)向下處理萨醒。

  • 思路如下:
  • 代碼如下:
_syncQueue = dispatch_queue_create("syncQueue", DISPATCH_QUEUE_CONCURRENT);

//! 讀取字符串
- (NSString *)someString {

    __block NSString *localSomeString;

    dispatch_sync(_syncQueue, ^{
        localSomeString = _someString;
    });

    return localSomeString;
}

- (void)setSomeString:(NSString *)someString {

     dispatch_barrier_async(_syncQueue, ^{
        _someString = someString;
    });
}

二斟珊、多用GCD,少用performSelector系列方法

performSelector系列方法的缺點(diǎn)有兩個(gè):

  1. performSelector系列方法可能引起內(nèi)存泄漏:
    在ARC環(huán)境下富纸,編譯器并不知道將要調(diào)用的選擇子是什么囤踩,有沒(méi)有返回值,返回值是什么胜嗓,所以ARC不能判斷返回值是否能釋放高职,因此ARC做了一個(gè)比較謹(jǐn)慎的做法:只添加retain,不添加release辞州。因此在有返回值或參數(shù)的時(shí)候可能導(dǎo)致內(nèi)存泄漏怔锌。
  2. performSelector系列方法的返回值只能是void或OC對(duì)象類型。
  3. performSelector系列方法最多只能傳入兩個(gè)參數(shù)变过。

因此可以使用GCD來(lái)代替performSelector系列方法:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
    //do something..
});

三埃元、掌握GCD及操作隊(duì)列的使用時(shí)機(jī)

GCD性能很棒,但在執(zhí)行后臺(tái)任務(wù)時(shí)媚狰,GCD并不一定是最佳選擇岛杀。在iOS開(kāi)發(fā)中,還有一種技術(shù)叫NSOperationQueue崭孤。GCD是基于C語(yǔ)言的API类嗤,性能較高。而NSOperationQueue是基于GCD的抽象辨宠。

使用NSOperationNSOperationQueue的優(yōu)點(diǎn):

  • 支持取消某個(gè)NSOperation
    在運(yùn)行任務(wù)前遗锣,可以在NSOperation對(duì)象上調(diào)用cancel方法,用以表明此任務(wù)不需要執(zhí)行嗤形。不過(guò)已經(jīng)啟動(dòng)的任務(wù)無(wú)法取消精偿。iOS 8之前,GCD隊(duì)列是無(wú)法取消的,GCD是“安排好之后就不管了(fire and forget)”笔咽。iOS 8之后搔预,支持dispatch_canceldispatch_block_cancel

  • NSOperation支持多任務(wù)操作的依賴關(guān)系:
    比如:任務(wù)A叶组、B拯田、C必須在任務(wù)D完成后執(zhí)行。

  • 支持通過(guò)KVO監(jiān)控NSOperation對(duì)象的屬性:
    例如:可以通過(guò)isCancelled屬性來(lái)判斷任務(wù)是否已取消扶叉,通過(guò)isFinished屬性來(lái)判斷任務(wù)是否已經(jīng)完成等等勿锅;

  • 支持指定NSOperationQueue的優(yōu)先級(jí):
    操作的優(yōu)先級(jí)表示此操作與隊(duì)列中其他操作之間的優(yōu)先關(guān)系帕膜,優(yōu)先級(jí)高的NSOperationQueue先執(zhí)行枣氧,優(yōu)先級(jí)低的后執(zhí)行。GCD的隊(duì)列也有優(yōu)先級(jí)垮刹,不過(guò)不是針對(duì)整個(gè)隊(duì)列的达吞;

  • 重用NSOperation對(duì)象:
    在開(kāi)發(fā)中你可以使用NSOperation的子類或者自己創(chuàng)建NSOperation對(duì)象來(lái)保存一些信息,可以在類中定義方法荒典,使得代碼能夠多次使用酪劫;

四、通過(guò)Dispatch Group機(jī)制寺董,根據(jù)系統(tǒng)資源狀況來(lái)執(zhí)行任務(wù)

dispatch groupGCD的一項(xiàng)特性覆糟,能夠把任務(wù)進(jìn)行分組管理,然后等待這組任務(wù)執(zhí)行完畢時(shí)會(huì)有通知遮咖,開(kāi)發(fā)者可以拿到結(jié)果然后繼續(xù)下一步操作滩字。
另外,通過(guò)dispatch group在并發(fā)隊(duì)列上同時(shí)執(zhí)行多項(xiàng)任務(wù)的時(shí)候御吞,GCD會(huì)根據(jù)系統(tǒng)資源狀態(tài)來(lái)幫忙調(diào)度這些并發(fā)執(zhí)行的任務(wù)麦箍。

五、使用dispatch_once來(lái)執(zhí)行只需要運(yùn)行一次的線程安全代碼

例如:我們開(kāi)發(fā)中寫一個(gè)單例陶珠,就可以使用dispatch_once

+ (instancetype)sharedInstance {
    
    static Class *manager = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[Class alloc] init];
    });

    return manager;
}

六挟裂、不要使用dispatch_get_current_queue

理由如下:

  • dispatch_get_current_queue 函數(shù)的行為常常與開(kāi)發(fā)者所預(yù)期的不同,此函數(shù)已經(jīng)廢棄揍诽,只應(yīng)做調(diào)試之用诀蓉。
  • 由于GCD是按層級(jí)來(lái)組織的,所以無(wú)法單用某個(gè)隊(duì)列對(duì)象來(lái)描述"當(dāng)前隊(duì)列"這一概念暑脆。
  • dispatch_get_current_queue 函數(shù)用于解決由不可以重入的代碼所引發(fā)的死鎖渠啤,然后能用此函數(shù)解決的問(wèn)題,通常也可以用"隊(duì)列特定數(shù)據(jù)"來(lái)解決饵筑。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末埃篓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子根资,更是在濱河造成了極大的恐慌架专,老刑警劉巖同窘,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異部脚,居然都是意外死亡想邦,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門委刘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)丧没,“玉大人,你說(shuō)我怎么就攤上這事锡移∨煌” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵淆珊,是天一觀的道長(zhǎng)夺饲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)施符,這世上最難降的妖魔是什么往声? 我笑而不...
    開(kāi)封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮戳吝,結(jié)果婚禮上浩销,老公的妹妹穿的比我還像新娘。我一直安慰自己听哭,他們只是感情好慢洋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著欢唾,像睡著了一般且警。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上礁遣,一...
    開(kāi)封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天斑芜,我揣著相機(jī)與錄音,去河邊找鬼祟霍。 笑死杏头,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的沸呐。 我是一名探鬼主播醇王,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼崭添!你這毒婦竟也來(lái)了寓娩?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎棘伴,沒(méi)想到半個(gè)月后寞埠,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年阱穗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饭冬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揪阶。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡昌抠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出遣钳,到底是詐尸還是另有隱情扰魂,我是刑警寧澤倦淀,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布愿棋,位于F島的核電站甘邀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏垮庐。R本人自食惡果不足惜松邪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哨查。 院中可真熱鬧,春花似錦邮府、人聲如沸浙于。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)紊服。三九已至檀轨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間欺嗤,已是汗流浹背参萄。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留煎饼,地道東北人讹挎。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像吆玖,于是被迫代替她去往敵國(guó)和親筒溃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355