GCD in Swift 3

作者: 桥下的阿卡迪亚 | 来源:发表于2016-09-23 14:07 被阅读1185次

本文假设你有一定的 GCD 和 Swift 基础。

iOS 下的多线程编程技术从底层往上分别是 NSThread、NSOperation、Grand Central Dispatch(GCD),这三个技术越往后抽象度越高,使用也越简单。GCD 无论在 Objective-C 时代,还是后 OC 的 Swift 时代,都是 iOS 开发者使用最多的多线程编程技术。

GCD 是使用 C 语言编写的。多年以来,一直使用 Objective-C 的开发者们很习惯 GCD 的底层 C 语言式的代码。这种风格一直保留到 Swift 推出两年后,到了 Swift 2 。无论 Swift 迭代了多少回,GCD 依然保留其原始的 C-Style。终于,到了 2016 年,全力研发 Swift 的苹果终于想起了 GCD 这么个东西,在 WWDC 2016 推出的 Swift 3 中完全更改了 GCD 的代码风格。

回顾

在 Swift < 3 中,我们写一个 GCD 代码可能是这样的:

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

我们创建一个串行队列,然后指派一个输出 Hello World 的异步任务给这个队列,一切看上去都很自然。然而唯一的缺点就是,这太不 Swift 了。

Swift < 3 中,Swift 标准库里面的 libdispach 是一从 C 导入的函数的集合。这也导致了在 Swift < 3 中使用 GCD 非常不符合 Swift 的语法,而且这些函数名在 Swift 中看上去也很怪异。

What's new?

我们再看看 Swift 3 中,上面的代码是如何写的:

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

很好,这很 Swift,或者说这很 OOP。

我们先简单看一看和之前到底有何不同。

  • 在之前的 GCD 中,我们写函数的顺序是,先确定异步还是同步操作,然后把队列作为参数传入函数,然后指派一个任务闭包。在 Swift 3 中,这个顺序反了过来,我们先指定一个队列,然后再选是异步还是同步操作,这更符合面向对象的语法特点。
  • 变量名更符合 Swift API 的设计规范

仔细看看

命名方式

从上述的引言中,我们可以看到在 Swift 3 中,我们熟悉的 GCD 类型名已经发生了比较大的改变,下划线被去掉,使用了大驼峰式命名法,不过好在他们还没有脱离原来的含义,下面是一张对照表:

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 更新操作,在之前的版本,我们通过这个函数获取主队列:

dispatch_get_main_queue()

现在我们用这个属性:

DispatchQueue.main

全局队列

在 iOS < 8 之前,我们有四种优先级的全局队列,他们分别是:

#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 之后,优先级的概念被苹果使用 QoS 替代了,Swift 3 中也一样。我们不再使用优先级,而是使用 QoS 来描述全局队列。简单地说,这两者之间的对应关系是这样的:

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() 方法,实际上就像指定它的优先级。当然你也可以不指定,默认就是 default。

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

创建队列

就像在前言中所举的例子,有时候我们想创建一个队列,之前我们是这么写的:

let queue = dispatch_queue_create("Kenneth", nil)

现在我们直接使用 init 函数:

let queue = DispatchQueue(label: "Kenneth")

这么写来创建一个并行队列:

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

任务

像之前所说的一样,在 Swift 3 中指派任务更加自然,也更加方便。你只需要在你所指定的队列后使用相应的方法(.sync、.async),然后使用闭包传入任务即可。

同步任务

使用 .sync 方法,例如:

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

Tips:请避免在主线程指定同步任务,否则你的主线程可能会锁死。

异步任务

使用 .async 方法,例如:

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

延时执行

之前我们在 GCD 中,想要指派一个任务延时执行(比如等待一个动画),需要写的代码十分复杂。我们来看看 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 时代是一个用来写单例的很好的工具,它保证任务只执行一次。然而在 Swift 3 中,这个函数被删除了。
在 Swift 中,好用又简洁的单例请使用 static let。

总结

随着 Swift 3 的正式发布,GCD 新型的使用方式将会被越多的人所认识。作为 iOS 开发者,我很乐于见到 GCD 新的语法更加现代化,更符合面向对象的思想,也更便于使用。下面是常用的 GCD 模板在 Swift 3 中的写法,供大家参考。

全局队列异步
DispatchQueue.global().async {
    //Something that wastes time
    DispatchQueue.main.async {
    //返回主线程
    }
}
延时操作,注意这里的单位是秒
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.5) {
    // 你想做啥
}
创建队列同步
let queue = DispatchQueue(label: "Kenneth")
queue.sync {
    print("Hello World")
}

相关文章

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

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

  • Swift5 - note1

    Swift 2 Error handing 增强 guard语法 协议支持扩展 Swift 3 新的GCD和Cor...

  • Swift语言版本历史

    swift2 Error handling增强·guard语法·协议支持扩展 swift3.新的GCD和Core ...

  • Swift-GCD

    对原Swift-GCD升级 SwiftGCD Swift-GCD Package GCDGroup, GCDQue...

  • Swift3使用GCD和DispatchQueues关于gcd

    关于对gcd 的使用,有几个链接写的还是相当不错的。Swift3使用GCD和DispatchQueueshttp:...

  • GCD in Swift 3

    本文假设你有一定的 GCD 和 Swift 基础。 iOS 下的多线程编程技术从底层往上分别是 NSThread、...

  • GCD

    iOS多线程 Swift4 GCD深入解析swift GCD 的一些高级用法GCD 之线程组(Dispatch G...

  • swift GCD-定时器(DispatchSourceTime

    前言: 了解swift GCD 与OC GCD请看我的其他总结文章,这篇文章只是对swift GCD定时器的一个实...

  • swift中GCD的使用详情

    想看swift3.0使用GCD,请点击GCD详解 想看swift3.0闭包的使用和介绍,请点击Swift版闭包使用...

  • Swift-GCD

    本篇文章介绍的是在Swift3语言下的GCD应用操作,针对的目标读者可以是没有GCD基础的初学者,也可以是对GCD...

网友评论

    本文标题:GCD in Swift 3

    本文链接:https://www.haomeiwen.com/subject/etqtyttx.html