关于GCD之asyncAfter详解

128 阅读4分钟

#含义:

//asyncAfter(wallDeadline: DispatchWallTime)
public func asyncAfter(wallDeadline: DispatchWallTime, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute work: @escaping @convention(block) () -> Void)
//asyncAfter(deadline: DispatchTime)
public func asyncAfter(deadline: DispatchTime, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute work: @escaping @convention(block) () -> Void)

这两个方法是用于在指定的时间之后异步执行代码块的方法,它们的区别在于传入参数的类型和含义。

  • asyncAfter(wallDeadline: DispatchWallTime, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute work: @escaping @convention(block) () -> Void): 这个方法使用 DispatchWallTime 类型的参数来指定绝对时间戳,表示代码块应该在指定的绝对时间之后执行。DispatchWallTime 是通过 DispatchTime 类型的 now() 方法和时间偏移量来创建的。

  • asyncAfter(deadline: DispatchTime, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], execute work: @escaping @convention(block) () -> Void): 这个方法使用 DispatchTime 类型的参数来指定相对时间,表示代码块应该在当前时间的基础上延迟一段时间后执行。DispatchTime 是通过 DispatchTime.now() + TimeInterval 的方式来创建的。

总结来说,这两个方法的主要区别在于参数的类型和含义。asyncAfter(wallDeadline:) 方法使用绝对时间戳,而 asyncAfter(deadline:) 方法使用相对时间。你可以根据自己的需求和场景选择使用合适的方法。

#例子:

  • asyncAfter(wallDeadline: DispatchWallTime)
let deadline = DispatchWallTime.now() + .seconds(5) // 在当前时间基础上延迟 5 秒执行
DispatchQueue.global().asyncAfter(wallDeadline: deadline) {
    // 在指定的绝对时间之后执行的代码块
    print("执行异步任务")
}

这个例子中,我们使用 DispatchWallTime 类型的参数来指定一个绝对时间戳。我们通过 DispatchWallTime.now() 获取当前时间,并加上 .seconds(5) 来表示相对当前时间延迟 5 秒执行代码块。这个方法适用于需要在具体的绝对时间点执行任务的场景,比如实现一个定时器,在某个特定时间触发某些操作。

  • asyncAfter(deadline: DispatchTime)
let deadline = DispatchTime.now() + .milliseconds(500) // 在当前时间基础上延迟 500 毫秒执行
DispatchQueue.main.asyncAfter(deadline: deadline) {
    // 在延迟一段时间后执行的代码块
    print("执行异步任务")
}

这个例子中,我们使用 DispatchTime 类型的参数来指定一个相对时间。我们通过 DispatchTime.now() 获取当前时间,并加上 .milliseconds(500) 表示相对当前时间延迟 500 毫秒执行代码块。这个方法适用于需要在一定延迟后执行任务的场景,比如界面上的动画效果、延迟加载数据等。 #原理: 这两个方法的底层实现原理是基于GCD(Grand Central Dispatch)框架。

GCD 是苹果提供的一种多线程编程技术,用于处理并发任务的调度和执行。它通过使用队列和任务块,将任务提交到适当的线程或队列中执行。

在这里,asyncAfter 方法的底层实现原理涉及到以下几个关键概念:

  1. Dispatch Queue(调度队列):GCD 中用于管理和执行任务的队列。它可以是串行队列(Serial Queue)或并发队列(Concurrent Queue),根据需要选择不同的队列类型。

  2. Dispatch Time(调度时间):表示 GCD 使用的时间值,用于控制任务的调度和延迟执行。其中,DispatchWallTime 是一个绝对时间戳,而 DispatchTime 则是一个相对时间。

  3. Dispatch Work Item(调度任务项):表示要执行的具体任务。它可以是一个普通的闭包(block),也可以是一个具有更多控制选项的自定义任务。

基于这些概念,asyncAfter 方法的底层实现大致可分为以下步骤:

  1. 创建一个 DispatchWorkItem 对象,封装要执行的代码块。

  2. 创建一个 DispatchTimeDispatchWallTime 对象,用于表示任务应该何时执行。

  3. 将任务块和时间参数提交给合适的调度队列(例如,DispatchQueue.global()DispatchQueue.main)。

GCD 框架根据指定的时间参数,在该时间点将任务块加入到对应的队列中。

当到达指定的时间点时,GCD 框架从相应的队列中取出任务块,并在适当的线程上执行。

总的来说,asyncAfter 方法利用 GCD 的调度队列和时间机制,实现了在指定时间之后异步执行代码块的功能。这样可以方便地控制任务的延时执行和定时触发,提高应用程序的并发性和响应性。