GCD in Swift 3

本文假設(shè)你有一定的 GCD 和 Swift 基礎(chǔ)。

iOS 下的多線程編程技術(shù)從底層往上分別是 NSThread烂琴、NSOperation嫌佑、Grand Central Dispatch(GCD)咖耘,這三個技術(shù)越往后抽象度越高,使用也越簡單缠沈。GCD 無論在 Objective-C 時代,還是后 OC 的 Swift 時代错蝴,都是 iOS 開發(fā)者使用最多的多線程編程技術(shù)洲愤。

GCD 是使用 C 語言編寫的。多年以來顷锰,一直使用 Objective-C 的開發(fā)者們很習(xí)慣 GCD 的底層 C 語言式的代碼柬赐。這種風(fēng)格一直保留到 Swift 推出兩年后,到了 Swift 2 官紫。無論 Swift 迭代了多少回肛宋,GCD 依然保留其原始的 C-Style。終于束世,到了 2016 年酝陈,全力研發(fā) Swift 的蘋果終于想起了 GCD 這么個東西,在 WWDC 2016 推出的 Swift 3 中完全更改了 GCD 的代碼風(fēng)格毁涉。

回顧

在 Swift < 3 中后添,我們寫一個 GCD 代碼可能是這樣的:

let queue = dispatch_queue_create("Kenneth", nil)
dispatch_async(queue) {
    print("Hello World")
}

我們創(chuàng)建一個串行隊列,然后指派一個輸出 Hello World 的異步任務(wù)給這個隊列薪丁,一切看上去都很自然遇西。然而唯一的缺點就是,這太不 Swift 了严嗜。

Swift < 3 中粱檀,Swift 標(biāo)準(zhǔn)庫里面的 libdispach 是一從 C 導(dǎo)入的函數(shù)的集合。這也導(dǎo)致了在 Swift < 3 中使用 GCD 非常不符合 Swift 的語法漫玄,而且這些函數(shù)名在 Swift 中看上去也很怪異茄蚯。

What's new?

我們再看看 Swift 3 中,上面的代碼是如何寫的:

let queue = DispatchQueue(label: "Kenneth")
queue.async {
    print("Hello World")
}

很好睦优,這很 Swift渗常,或者說這很 OOP。

我們先簡單看一看和之前到底有何不同汗盘。

  • 在之前的 GCD 中皱碘,我們寫函數(shù)的順序是,先確定異步還是同步操作隐孽,然后把隊列作為參數(shù)傳入函數(shù)癌椿,然后指派一個任務(wù)閉包健蕊。在 Swift 3 中,這個順序反了過來踢俄,我們先指定一個隊列缩功,然后再選是異步還是同步操作,這更符合面向?qū)ο蟮恼Z法特點都办。
  • 變量名更符合 Swift API 的設(shè)計規(guī)范

仔細(xì)看看

命名方式

從上述的引言中嫡锌,我們可以看到在 Swift 3 中,我們熟悉的 GCD 類型名已經(jīng)發(fā)生了比較大的改變琳钉,下劃線被去掉势木,使用了大駝峰式命名法,不過好在他們還沒有脫離原來的含義槽卫,下面是一張對照表:

C Swift
dispatch_object_t DispatchObject
dispatch_queue_t DispatchQueue
dispatch_group_t DispatchGroup
dispatch_data_t DispatchData
dispatch_io_t DispatchIO
dispatch_semaphore_t DispatchSemaphore
dispatch_source_t DispatchSource
dispatch_time_t DispatchTime, DispatchWalltime
C Swift
dispatch_fd_t Int32
dispatch_block_t () -> ()
dispatch_queue_attr_t DispatchQueueAttributes

隊列

主隊列

主隊列通常被用來做我們 App 的 UI 更新操作跟压,在之前的版本,我們通過這個函數(shù)獲取主隊列:

dispatch_get_main_queue()

現(xiàn)在我們用這個屬性:

DispatchQueue.main

全局隊列

在 iOS < 8 之前歼培,我們有四種優(yōu)先級的全局隊列震蒋,他們分別是:

#define DISPATCH_QUEUE_PRIORITY_HIGH         2  
#define DISPATCH_QUEUE_PRIORITY_DEFAULT      0  
#define DISPATCH_QUEUE_PRIORITY_LOW          (-2)  
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND   INT16_MIN  

在 iOS >= 8 之后,優(yōu)先級的概念被蘋果使用 QoS 替代了躲庄,Swift 3 中也一樣查剖。我們不再使用優(yōu)先級,而是使用 QoS 來描述全局隊列噪窘。簡單地說笋庄,這兩者之間的對應(yīng)關(guān)系是這樣的:

Priority DispatchQoS
DISPATCH_QUEUE_PRIORITY_HIGH .userInitiated
DISPATCH_QUEUE_PRIORITY_DEFAULT .default
DISPATCH_QUEUE_PRIORITY_LOW .utility
DISPATCH_QUEUE_PRIORITY_BACKGROUND .background

在 Swift 3 中,獲取全局隊列需要使用這個方法:

DispatchQueue.global(qos: DispatchQoS.*)

我們將 QoS 傳入 global() 方法倔监,實際上就像指定它的優(yōu)先級直砂。當(dāng)然你也可以不指定,默認(rèn)就是 default浩习。

DispatchQueue.global()      // 等于 DispatchQueue.global(qos: .default)

創(chuàng)建隊列

就像在前言中所舉的例子静暂,有時候我們想創(chuàng)建一個隊列,之前我們是這么寫的:

let queue = dispatch_queue_create("Kenneth", nil)

現(xiàn)在我們直接使用 init 函數(shù):

let queue = DispatchQueue(label: "Kenneth")

這么寫來創(chuàng)建一個并行隊列:

let conQueue = DispatchQueue(label: "Kenneth", attributes: .concurrent)

任務(wù)

像之前所說的一樣谱秽,在 Swift 3 中指派任務(wù)更加自然洽蛀,也更加方便。你只需要在你所指定的隊列后使用相應(yīng)的方法(.sync疟赊、.async)郊供,然后使用閉包傳入任務(wù)即可。

同步任務(wù)

使用 .sync 方法近哟,例如:

let queue = DispatchQueue(label: "Kenneth")
queue.sync {
    print("Hello World")
}

Tips:請避免在主線程指定同步任務(wù)驮审,否則你的主線程可能會鎖死。

異步任務(wù)

使用 .async 方法,例如:

let queue = DispatchQueue(label: "Kenneth")
queue.async {
    print("Hello World")
}

延時執(zhí)行

之前我們在 GCD 中头岔,想要指派一個任務(wù)延時執(zhí)行(比如等待一個動畫)塔拳,需要寫的代碼十分復(fù)雜鼠证。我們來看看 Swift 3 中是怎樣的:

let delay = DispatchTime.now() + 3.5

DispatchQueue.main.asyncAfter(deadline: delay) {
    // 你想做啥
}

Boom峡竣!

Tips:要注意這里的單位是秒(s),如果你想更改單位的話量九,可以使用 DispatchTime 的 enum:

  • .seconds(Int)
  • .milliseconds(Int)
  • .microseconds(Int)
  • .nanoseconds(Int)

dispatch_once

dispatch_once 在 OC 時代是一個用來寫單例的很好的工具适掰,它保證任務(wù)只執(zhí)行一次。然而在 Swift 3 中荠列,這個函數(shù)被刪除了类浪。
在 Swift 中,好用又簡潔的單例請使用 static let肌似。

總結(jié)

隨著 Swift 3 的正式發(fā)布费就,GCD 新型的使用方式將會被越多的人所認(rèn)識。作為 iOS 開發(fā)者川队,我很樂于見到 GCD 新的語法更加現(xiàn)代化力细,更符合面向?qū)ο蟮乃枷耄哺阌谑褂霉潭睢O旅媸浅S玫?GCD 模板在 Swift 3 中的寫法眠蚂,供大家參考。

全局隊列異步
DispatchQueue.global().async {
    //Something that wastes time
    DispatchQueue.main.async {
    //返回主線程
    }
}
延時操作斗躏,注意這里的單位是秒
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.5) {
    // 你想做啥
}
創(chuàng)建隊列同步
let queue = DispatchQueue(label: "Kenneth")
queue.sync {
    print("Hello World")
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逝慧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子啄糙,更是在濱河造成了極大的恐慌笛臣,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隧饼,死亡現(xiàn)場離奇詭異沈堡,居然都是意外死亡,警方通過查閱死者的電腦和手機桑李,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門踱蛀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人贵白,你說我怎么就攤上這事率拒。” “怎么了禁荒?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵猬膨,是天一觀的道長。 經(jīng)常有香客問我,道長勃痴,這世上最難降的妖魔是什么谒所? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮沛申,結(jié)果婚禮上劣领,老公的妹妹穿的比我還像新娘。我一直安慰自己铁材,他們只是感情好尖淘,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著著觉,像睡著了一般村生。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上饼丘,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天趁桃,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛佛掖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播忽肛,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼烂斋!你這毒婦竟也來了屹逛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤汛骂,失蹤者是張志新(化名)和其女友劉穎罕模,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帘瞭,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡淑掌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蝶念。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抛腕。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖媒殉,靈堂內(nèi)的尸體忽然破棺而出担敌,到底是詐尸還是另有隱情,我是刑警寧澤廷蓉,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布全封,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏刹悴。R本人自食惡果不足惜行楞,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望土匀。 院中可真熱鬧子房,春花似錦、人聲如沸恒削。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钓丰。三九已至,卻和暖如春每币,著一層夾襖步出監(jiān)牢的瞬間携丁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工兰怠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留梦鉴,地道東北人。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓揭保,卻偏偏與公主長得像肥橙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子秸侣,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

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

  • 盡管 Grand Central Dispatch (GCD)已經(jīng)存在一段時間了存筏,但并非每個人都知道怎么使用它。這...
    coderFamer閱讀 7,394評論 1 16
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫味榛、插件椭坚、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,098評論 4 62
  • 作者:GABRIEL THEODOROPOULOS,原文鏈接搏色,原文日期:2016-11-16譯者:小鍋善茎;校對:sa...
    梁杰_numbbbbb閱讀 3,209評論 0 7
  • 周日的陽光很好,溫度又升起來频轿。下午家人齊動手包了白菜餡餃子垂涯,我和女兒給母親送到醫(yī)院。 這次母親屬于住...
    金色麥子閱讀 418評論 0 0
  • 原來一個人對另一個人刻骨的相思 對方真的一無所感 有情和無情之間 亙著一條永恒無法跨越的大河 流淌的是時光 這是多...
    浮生半日michelle閱讀 188評論 0 0