如何在 Swift 3、4 和 5 中编写 dispatch_after GCD?
How do I write dispatch_after GCD in Swift 3, 4, and 5?
在 Swift 2 中,我能够使用 dispatch_after
使用 grand central dispatch 延迟一个动作:
var dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(dispatchTime, dispatch_get_main_queue(), {
// your function here
})
但这似乎不再编译自 Swift 3. 在现代 Swift 中编写此代码的首选方式是什么?
致电DispatchQueue.main.after(when: DispatchTime, execute: () -> Void)
我强烈建议使用 Xcode 工具转换为 Swift 3(编辑 > 转换 > 为当前 Swift 语法)。它帮我抓住了这个
语法很简单:
// to run something in 0.1 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
// your code here
}
请注意,上面将 seconds
添加为 Double
的语法似乎是混淆的根源(尤其是因为我们习惯于添加 nsec)。 "add seconds as Double
" 语法之所以有效,是因为 deadline
是一个 DispatchTime
,并且在幕后,有一个 +
运算符需要一个 Double
并加上那么多秒到 DispatchTime
:
public func +(time: DispatchTime, seconds: Double) -> DispatchTime
但是,如果你真的想在 DispatchTime
上加上一个毫秒、微秒或纳秒的整数,你也可以在 DispatchTime
上加上一个 DispatchTimeInterval
。这意味着您可以:
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
os_log("500 msec seconds later")
}
DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(1_000_000)) {
os_log("1m μs seconds later")
}
DispatchQueue.main.asyncAfter(deadline: .now() + .nanoseconds(1_500_000_000)) {
os_log("1.5b nsec seconds later")
}
由于 DispatchTime
class.
中 +
运算符的这种单独重载方法,这些都可以无缝工作
public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime
有人问如何取消已派发的任务。为此,请使用 DispatchWorkItem
。例如,这将启动一个将在五秒内触发的任务,或者如果视图控制器被关闭并释放,它的 deinit
将取消任务:
class ViewController: UIViewController {
private var item: DispatchWorkItem?
override func viewDidLoad() {
super.viewDidLoad()
item = DispatchWorkItem { [weak self] in
self?.doSomething()
self?.item = nil
}
DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: item!)
}
deinit {
item?.cancel()
}
func doSomething() { ... }
}
请注意 DispatchWorkItem
中 [weak self]
捕获列表的使用。这对于避免强引用循环至关重要。另请注意,这不会执行先发制人的取消,而只是阻止任务开始(如果尚未开始)。但是,如果它在遇到 cancel()
调用时已经启动,则该块将完成执行(除非您在块内手动检查 isCancelled
)。
Swift 4:
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
// Code
}
对于时间.seconds(Int)
,也可以使用.microseconds(Int)
和.nanoseconds(Int)
。
如果你只是想要
中的延迟功能
Swift 4 & 5
func delay(interval: TimeInterval, closure: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + interval) {
closure()
}
}
您可以像这样使用它:
delay(interval: 1) {
print("Hi!")
}
在Swift 3 发布后,还必须添加@escaping
func delay(_ delay: Double, closure: @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
closure()
}
}
Swift 4
您可以在 DispatchQueue 上创建扩展并添加函数延迟,它在内部使用 DispatchQueue
asyncAfter 函数
extension DispatchQueue {
static func delay(_ delay: DispatchTimeInterval, closure: @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: closure)
}
}
并使用
DispatchQueue.delay(.milliseconds(10)) {
print("task to be done")
}
您可以使用
DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(100)) {
// Code
}
接受的答案有点不同。
Swift 4
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 + .milliseconds(500) +
.microseconds(500) + .nanoseconds(1000)) {
print("Delayed by 0.1 second + 500 milliseconds + 500 microseconds +
1000 nanoseconds)")
}
试试这个
let when = DispatchTime.now() + 1.5
DispatchQueue.main.asyncAfter(deadline: when) {
//some code
}
在 Swift 4.1 和 Xcode 9.4.1 中
简单的答案是...
//To call function after 5 seconds time
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
//Here call your function
}
None 个答案在非主线程上提到 运行,所以加上我的 2 美分。
在主队列(主线程)
let mainQueue = DispatchQueue.main
let deadline = DispatchTime.now() + .seconds(10)
mainQueue.asyncAfter(deadline: deadline) {
// ...
}
或
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(10)) {
// ...
}
在全局队列(非主线程,基于指定的 QOS)。
let backgroundQueue = DispatchQueue.global()
let deadline = DispatchTime.now() + .milliseconds(100)
backgroundQueue.asyncAfter(deadline: deadline, qos: .background) {
// ...
}
或
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + .milliseconds(100), qos: .background) {
// ...
}
Swift 5岁及以上
DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
// code to execute
})
在 Swift 2 中,我能够使用 dispatch_after
使用 grand central dispatch 延迟一个动作:
var dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(dispatchTime, dispatch_get_main_queue(), {
// your function here
})
但这似乎不再编译自 Swift 3. 在现代 Swift 中编写此代码的首选方式是什么?
致电DispatchQueue.main.after(when: DispatchTime, execute: () -> Void)
我强烈建议使用 Xcode 工具转换为 Swift 3(编辑 > 转换 > 为当前 Swift 语法)。它帮我抓住了这个
语法很简单:
// to run something in 0.1 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
// your code here
}
请注意,上面将 seconds
添加为 Double
的语法似乎是混淆的根源(尤其是因为我们习惯于添加 nsec)。 "add seconds as Double
" 语法之所以有效,是因为 deadline
是一个 DispatchTime
,并且在幕后,有一个 +
运算符需要一个 Double
并加上那么多秒到 DispatchTime
:
public func +(time: DispatchTime, seconds: Double) -> DispatchTime
但是,如果你真的想在 DispatchTime
上加上一个毫秒、微秒或纳秒的整数,你也可以在 DispatchTime
上加上一个 DispatchTimeInterval
。这意味着您可以:
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
os_log("500 msec seconds later")
}
DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(1_000_000)) {
os_log("1m μs seconds later")
}
DispatchQueue.main.asyncAfter(deadline: .now() + .nanoseconds(1_500_000_000)) {
os_log("1.5b nsec seconds later")
}
由于 DispatchTime
class.
+
运算符的这种单独重载方法,这些都可以无缝工作
public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime
有人问如何取消已派发的任务。为此,请使用 DispatchWorkItem
。例如,这将启动一个将在五秒内触发的任务,或者如果视图控制器被关闭并释放,它的 deinit
将取消任务:
class ViewController: UIViewController {
private var item: DispatchWorkItem?
override func viewDidLoad() {
super.viewDidLoad()
item = DispatchWorkItem { [weak self] in
self?.doSomething()
self?.item = nil
}
DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: item!)
}
deinit {
item?.cancel()
}
func doSomething() { ... }
}
请注意 DispatchWorkItem
中 [weak self]
捕获列表的使用。这对于避免强引用循环至关重要。另请注意,这不会执行先发制人的取消,而只是阻止任务开始(如果尚未开始)。但是,如果它在遇到 cancel()
调用时已经启动,则该块将完成执行(除非您在块内手动检查 isCancelled
)。
Swift 4:
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
// Code
}
对于时间.seconds(Int)
,也可以使用.microseconds(Int)
和.nanoseconds(Int)
。
如果你只是想要
中的延迟功能Swift 4 & 5
func delay(interval: TimeInterval, closure: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + interval) {
closure()
}
}
您可以像这样使用它:
delay(interval: 1) {
print("Hi!")
}
在Swift 3 发布后,还必须添加@escaping
func delay(_ delay: Double, closure: @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
closure()
}
}
Swift 4
您可以在 DispatchQueue 上创建扩展并添加函数延迟,它在内部使用 DispatchQueue
asyncAfter 函数
extension DispatchQueue {
static func delay(_ delay: DispatchTimeInterval, closure: @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: closure)
}
}
并使用
DispatchQueue.delay(.milliseconds(10)) {
print("task to be done")
}
您可以使用
DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(100)) {
// Code
}
接受的答案有点不同。
Swift 4
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 + .milliseconds(500) +
.microseconds(500) + .nanoseconds(1000)) {
print("Delayed by 0.1 second + 500 milliseconds + 500 microseconds +
1000 nanoseconds)")
}
试试这个
let when = DispatchTime.now() + 1.5
DispatchQueue.main.asyncAfter(deadline: when) {
//some code
}
在 Swift 4.1 和 Xcode 9.4.1 中
简单的答案是...
//To call function after 5 seconds time
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
//Here call your function
}
None 个答案在非主线程上提到 运行,所以加上我的 2 美分。
在主队列(主线程)
let mainQueue = DispatchQueue.main
let deadline = DispatchTime.now() + .seconds(10)
mainQueue.asyncAfter(deadline: deadline) {
// ...
}
或
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(10)) {
// ...
}
在全局队列(非主线程,基于指定的 QOS)。
let backgroundQueue = DispatchQueue.global()
let deadline = DispatchTime.now() + .milliseconds(100)
backgroundQueue.asyncAfter(deadline: deadline, qos: .background) {
// ...
}
或
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + .milliseconds(100), qos: .background) {
// ...
}
Swift 5岁及以上
DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
// code to execute
})