Swift 3必看:從使用場景瞭解GCD新API

swift 3中對C層級的GCD的API進行了徹頭徹尾的改變。本文將從實際使用場景來了解一下新的api使用。git

dispatch_async

一個常見的場景就是在一個全局隊列進行一些操做後切換到主線程配置UI。如今是這麼寫:github

DispatchQueue.global().async {
    // code
    DispatchQueue.main.async {
        // 主線程中
    }
}複製代碼

global()是一個有着默認參數的靜態函數:swift

class DispatchQueue : DispatchObject {
    public  class var main: DispatchQueue public class func global(qos: DispatchQoS.QoSClass = default) -> DispatchQueue }複製代碼

sync

若是想同步執行操做,和async相似,調用sync就能夠了:api

DispatchQueue.global().sync {
    // 同步執行
}複製代碼

優先級:DispatchQoS

咱們知道,GCD 的默認隊列優先級有四個:安全

  • DISPATCH_QUEUE_PRIORITY_HIGH
  • DISPATCH_QUEUE_PRIORITY_DEFAULT
  • DISPATCH_QUEUE_PRIORITY_LOW
  • DISPATCH_QUEUE_PRIORITY_BACKGROUND

如今則改成了QoSClass枚舉閉包

public enum QoSClass {

        case background

        case utility

        case `default`

        case userInitiated

        case userInteractive

        case unspecified

        public init?(rawValue: qos_class_t)

        public var rawValue: qos_class_t { get }
    }複製代碼

這些命名比原先的更加友好,能更好表達這個操做的意圖。併發

和原有的對應關係是:app

* DISPATCH_QUEUE_PRIORITY_HIGH:         .userInitiated
* DISPATCH_QUEUE_PRIORITY_DEFAULT:      .default
* DISPATCH_QUEUE_PRIORITY_LOW:          .utility
* DISPATCH_QUEUE_PRIORITY_BACKGROUND:   .background複製代碼

建立隊列

DispatchQueue的默認初始化方法建立的就是一個同步隊列,若是要建立併發的隊列,在attributes中聲明concurrent。async

// 同步隊列
let serialQueue = DispatchQueue(label: "queuename")

// 併發隊列
let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)複製代碼

推遲時間後執行

原先的dispatch_time_t如今由DispatchTime對象表示。能夠用靜態方法now得到當前時間,而後再經過加上一個DispatchTimeInterval枚舉來得到一個須要延遲的時間。ide

let delay = DispatchTime.now() + DispatchTimeInterval.seconds(60)
DispatchQueue.main.asyncAfter(deadline: delay) { 
    // 延遲執行
}複製代碼

這裏也能夠直接加上一個秒數。

let three = DispatchTime.now() + 3.0複製代碼

由於DispatchTime中自定義了+號。

public func +(time: DispatchTime, seconds: Double) -> DispatchTime複製代碼

DispatchGroup

若是想在dispatch_queue中全部的任務執行完成後再作某種操做可使用DispatchGroup。原先的dispatch_group_t由如今的DispatchGroup對象代替。

let group = DispatchGroup()

let queueBook = DispatchQueue(label: "book")
queueBook.async(group: group) {
    // 下載圖書
}
let queueVideo = DispatchQueue(label: "video")
queueVideo.async(group: group) {
    // 下載視頻
}

group.notify(queue: DispatchQueue.main) { 
    // 下載完成
}複製代碼

DispatchGroup會在組裏的操做都完成後執行notify。 若是有多個併發隊列在一個組裏,咱們想在這些操做執行完了再繼續,調用wait

group.wait()複製代碼

DispatchWorkItem

使用DispatchWorkItem代替原來的dispatch_block_t。 在DispatchQueue執行操做除了直接傳了一個() -> Void類型的閉包外,還能夠傳入一個DispatchWorkItem。

public func sync(execute workItem: DispatchWorkItem)

    public func async(execute workItem: DispatchWorkItem)複製代碼

DispatchWorkItem的初始化方法能夠配置Qos和DispatchWorkItemFlags,可是這兩個參數都有默認參數,因此也能夠只傳入一個閉包。

public init(qos: DispatchQoS = default, flags: DispatchWorkItemFlags = default, block: @escaping @convention(block) () -> ())

let workItem = DispatchWorkItem { 
    // TODO:
}複製代碼

DispatchWorkItemFlags枚舉中assignCurrentContext表示QoS根據建立時的context決定。 值得一提的是DispatchWorkItem也有wait方法,使用方式和group同樣。調用會等待這個workItem執行完。

let myQueue = DispatchQueue(label: "my.queue", attributes: .concurrent)
let workItem = DispatchWorkItem {
    sleep(1)
    print("done")
}
myQueue.async(execute: workItem)
print("before waiting")
workItem.wait()
print("after waiting")複製代碼

barrier

假設咱們有一個併發的隊列用來讀寫一個數據對象。若是這個隊列裏的操做是讀的,那麼能夠多個同時進行。若是有寫的操做,則必須保證在執行寫入操做時,不會有讀取操做在執行,必須等待寫入完成後才能讀取,不然就可能會出現讀到的數據不對。在以前咱們用dipatch_barrier實現。 如今屬性放在了DispatchWorkItemFlags裏。

let wirte = DispatchWorkItem(flags: .barrier) { 
    // write data
}
let dataQueue = DispatchQueue(label: "data", attributes: .concurrent)
dataQueue.async(execute: wirte)複製代碼

信號量

爲了線程安全的統計數量,咱們會使用信號量做計數。原來的dispatch_semaphore_t如今用DispatchSemaphore對象表示。 初始化方法只有一個,傳入一個Int類型的數。

let semaphore = DispatchSemaphore(value: 5)

 // 信號量減一
semaphore.wait()

 //信號量加一
semaphore.signal()複製代碼

dispatch_once被廢棄

在swift 3中已經被廢棄了。 簡單的建議就是一些初始化場景就用懶加載吧。

// Examples of dispatch_once replacements with global or static constants and variables. 
// In all three, the initialiser is called only once. 

// Static properties (useful for singletons).
class Object {
    static let sharedInstance = Object()
}

// Global constant.
let constant = Object()

// Global variable.
var variable: Object = {
    let variable = Object()
    variable.doSomething()
    return variable
}()複製代碼

歡迎關注個人微博:@沒故事的卓同窗

相關連接:

SE0088-Modernize libdispatch for Swift 3 naming conventions

Concurrent Programming With GCD in Swift 3

相關文章
相關標籤/搜索