专栏名称: Cocoa开发者社区
CocoaChina苹果开发中文社区官方微信,提供教程资源、app推广营销、招聘、外包及培训信息、各类沙龙交流活动以及更多开发者服务。
目录
相关文章推荐
51好读  ›  专栏  ›  Cocoa开发者社区

Swift 3必看:从使用场景了解GCD新API

Cocoa开发者社区  · 公众号  · ios  · 2016-10-13 08:10

正文

请到「今天看啥」查看全文


▲点击上方“ CocoaChina ”关注即可免费学习iOS开发


原文链接:http://www.jianshu.com/p/fc78dab5736f


swift 3中对C层级的GCD的API进行了彻头彻尾的改变。本文将从实际使用场景来了解一下新的api使用。


dispatch_async


一个常见的场景就是在一个全局队列进行一些操作后切换到主线程配置UI。现在是这么写:


DispatchQueue.global().async {

// code

DispatchQueue.main.async {

// 主线程中

}

}


global()是一个有着默认参数的静态函数:


class DispatchQueue : DispatchObject {

public  class var main: DispatchQueue

public class func global(qos: DispatchQoS.QoSClass = default) -> DispatchQueue

}


sync


如果想同步执行操作,和async类似,调用sync就可以了:


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 }

}


这些命名比原先的更加友好,能更好表达这个操作的意图。



和原有的对应关系是:


* DISPATCH_QUEUE_PRIORITY_HIGH:         .userInitiated

* DISPATCH_QUEUE_PRIORITY_DEFAULT:      .default

* DISPATCH_QUEUE_PRIORITY_LOW:          .utility

* DISPATCH_QUEUE_PRIORITY_BACKGROUND:   .background


创建队列


DispatchQueue的默认初始化方法创建的就是一个同步队列,如果要创建并发的队列,在attributes中声明concurrent。


// 同步队列

let serialQueue = DispatchQueue(label: "queuename")

// 并发队列

let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)


推迟时间后执行


原先的dispatch_time_t现在由DispatchTime对象表示。可以用静态方法now获得当前时间,然后再通过加上一个DispatchTimeInterval枚举来获得一个需要延迟的时间。


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



微信号: CocoaChinabbs


▲长按二维码“识别”关注 即可免费学习 iOS 开发

月薪十万、出任CEO、赢娶白富美、走上人生巅峰不是梦

-------- ----------------- -------------

商务合作QQ:2408167315

投稿邮箱:[email protected]







请到「今天看啥」查看全文


推荐文章
中国经济网  ·  有没有教养只看这一点丨可读
8 年前
上海预警发布  ·  明天雨渐止 本周入夏有戏
7 年前