swift 多线程GCD和延时调用
来源:互联网 发布:回收站清空恢复软件 编辑:程序博客网 时间:2024/04/28 17:50
GCD 是一种非常方便的使用多线程的方式。通过使用 GCD,我们可以在确保尽量简单的语法的前提下进行灵活的多线程编程。在 “复杂必死” 的多线程编程中,保持简单就是避免错误的金科玉律。好消息是在 Swift 中是可以无缝使用 GCD 的 API 的,而且得益于闭包特性的加入,使用起来比之前在 Objective-C 中更加简单方便。在这里我不打算花费很多时间介绍 GCD 的语法和要素,如果这么做的话就可以专门为 GCD 写上一节了。在下面我给出了一个日常里最通常会使用到的例子 (说这个例子能覆盖到日常的 GCD 使用的 50% 以上也不为过),来展示一下 Swift 里的 GCD 调用会是什么样子:
01
// 创建目标队列
02
let workingQueue = dispatch_queue_create(
"my_queue"
, nil)
03
04
// 派发到刚创建的队列中,GCD 会负责进行线程调度
05
dispatch_async(workingQueue) {
06
// 在 workingQueue 中异步进行
07
print(
"努力工作"
)
08
NSThread.sleepForTimeInterval(2)
// 模拟两秒的执行时间
09
10
dispatch_async(dispatch_get_main_queue()) {
11
// 返回到主线程更新 UI
12
print(
"结束工作,更新 UI"
)
13
}
14
}
在日常的开发工作中,我们经常会遇到这样的需求:在 xx 秒后执行某个方法。比如切换界面 2 秒后开始播一段动画,或者提示框出现 3 秒后自动消失等等。以前在 Objective-C 中,我们可以使用一个 NSObject 的实例方法,-performSelector:withObject:afterDelay: 来指定在若干时间后执行某个 selector。在 Swift 2 之前,如果你新建一个 Swift 的项目,并且试图使用这个方法 (或者这个方法的其他一切变形) 的话,会发现这个方法并不存在。在 Swift 2 中虽然这一系列 performSelector 的方法被加回了标准库,但是由于 Swift 中创建一个 selector 并不是一件安全的事情 (你需要通过字符串来创建,这在之后代码改动时会很危险),所以最好尽可能的话避免使用这个方法。另外,原来的 performSelector: 这套东西在 ARC 下并不是安全的。ARC 为了确保参数在方法运行期间的存在,在无法准确确定参数内存情况的时候,会将输入参数在方法开始时先进行 retain,然后在最后 release。而对于 performSelector: 这个方法我们并没有机会为被调用的方法指定参数,于是被调用的 selector 的输入有可能会是指向未知的垃圾内存地址,然后...HOHO,要命的是这种崩溃还不能每次重现,想调试?见鬼去吧..
但是如果不论如何,我们都还想继续做延时调用的话应该怎么办呢?最容易想到的是使用 NSTimer 来创建一个若干秒后调用一次的计时器。但是这么做我们需要创建新的对象,和一个本来并不相干的 NSTimer 类扯上关系,同时也会用到 Objective-C 的运行时特性去查找方法等等,总觉着有点笨重。其实 GCD 里有一个很好用的延时调用我们可以加以利用写出很漂亮的方法来,那就是 dispatch_after。最简单的使用方法看起来是这样的:
1
let
time
: NSTimeInterval = 2.0
2
let delay = dispatch_time(DISPATCH_TIME_NOW,
3
Int64(
time
* Double(NSEC_PER_SEC)))
4
dispatch_after(delay, dispatch_get_main_queue()) {
5
print(
"2 秒后输出"
)
6
}
代码非常简单,代码非常简单,并没什么值得详细说明的。只是每次写这么多的话也挺累的,在这里我们可以稍微将它封装的好用一些,最好再加上取消的功能。在 iOS 8 中 GCD 得到了惊人的进化,现在我们可以通过将一个 dispatch_block_t 对象传递给 dispatch_block_cancel,来取消一个正在等待执行的 block。取消一个任务这样的特性,这在以前是 NSOperation 的专利,但是现在我们使用 GCD 也能达到同样的目的了。这里我们将类似地来尝试实现 delay call 的取消,整个封装也许有点长,但我还是推荐一读。大家也可以把它当作练习材料检验一下自己的 Swift 基础语法的掌握和理解的情况:
01
import Foundation
02
03
typealias Task = (cancel : Bool) -> Void
04
05
func delay(
time
:NSTimeInterval, task:()->()) -> Task? {
06
07
func dispatch_later(block:()->()) {
08
dispatch_after(
09
dispatch_time(
10
DISPATCH_TIME_NOW,
11
Int64(
time
* Double(NSEC_PER_SEC))),
12
dispatch_get_main_queue(),
13
block)
14
}
15
16
var closure: dispatch_block_t? = task
17
var result: Task?
18
19
let delayedClosure: Task = {
20
cancel in
21
if
let internalClosure = closure {
22
if
(cancel ==
false
) {
23
dispatch_async(dispatch_get_main_queue(), internalClosure);
24
}
25
}
26
closure = nil
27
result = nil
28
}
29
30
result = delayedClosure
31
32
dispatch_later {
33
if
let delayedClosure = result {
34
delayedClosure(cancel:
false
)
35
}
36
}
37
38
return
result;
39
}
40
41
func cancel(task:Task?) {
42
task?(cancel:
true
)
43
}
delay(2) { print("2 秒后输出") }
想要取消的话,我们可以先保留一个对 Task 的引用,然后调用 cancel:
let task = delay(5) { print("拨打 110") }
// 仔细想一想..
// 还是取消为妙..
cancel(task)
- swift 多线程GCD和延时调用
- swift gcd 延时调用封装
- GCD 和延时调用
- GCD 和延时调用
- GCD 和延时调用2
- SWift 的多线程延时
- iOS多线程(GCD)(swift)
- GCD延时操作Dispatch_after swift写法
- 【Swift】GCD多线程和BlockOperation实用代码块
- Swift 4.0中 GCD定时器写法,及延时操作
- GCD和多线程
- 多线程 GCD和NSOperation
- NSThread多线程和GCD多线程
- iOS开发 多线程和GCD
- [多线程]NSThread, NSOperation 和 GCD
- iOS中GCD和多线程
- 多线程GCD 和 NSOperationQueue 多线程编程4 - GCD
- GCD延时执行
- AndroidStudio配置SVN以及使用代码管理
- 安装linux kernel headers
- sqlite查询数据库去除重复记录
- Javascript中switch case的一个细节
- [李景山php]每天laravel-20160825|Encrypter
- swift 多线程GCD和延时调用
- 二、Hystrix隔离服务的实现原理---线程池隔离
- Java开发水吧点饮品系统(顶层父类对象做接口参数)
- ObjectArx自定义实体入门(C++)及注意事项
- linux的touch命令
- 51nod 1381 硬币游戏
- android多渠道快速打包
- python sqlalchemy 写数据
- Netty拆包粘包以及编解码技术