IOS - DispatchQueue.main.asyncAfter(deadline : . now()) 和 perform(_:with:afterDelay:) 之间的区别,延迟为 0

标签 ios objective-c swift grand-central-dispatch foundation

我意识到使用 DispatchQueue.main.asyncAfter(deadline: .now())perform(_:with:afterDelay:0) 是有区别的当主队列“忙”时。

请注意,在我的情况下,perform(_:with:afterDelay:) 是从主队列调用的。

看起来 DispatchQueue.main.asyncAfter(deadline: .now()) 在下一个运行循环中立即执行任务而不关心主队列但是 perform(_:with:afterDelay :) 0 延迟将等待并仅在主队列“空闲”时执行任务(可能不会在下一个运行循环中调用)。

根据 Apple 文档 perform(_:with:afterDelay:)

Specifying a delay of 0 does not necessarily cause the selector to be performed immediately. The selector is still queued on the thread’s run loop and performed as soon as possible.

我不确定我是否理解正确,所以任何人都可以帮我解释一下它们之间到底有什么区别吗? 尽快执行是什么意思?

我发现了同样的问题 here但似乎这不是我想要的。

最佳答案

我创建了这个独立测试来探索这个主题。

class ViewController: UIViewController {

    @objc func test1(_ info: Any) {
        guard let str = info as? String else { return }
        sleep(1)
        print(str)

        if str != "selector 3" {
            self.perform(#selector(test1), with: "selector 3", afterDelay: 0)
        }

        DispatchQueue.main.asyncAfter(deadline: .now()) {
            sleep(1)
            print("dispatch 4 queued by \(str)")
        }

    }


    @IBAction func test(_ sender: UIButton) {
        print("begin test")

        self.perform(#selector(test1), with: "selector 1", afterDelay: 0)

        DispatchQueue.main.asyncAfter(deadline: .now()) {
            DispatchQueue.main.asyncAfter(deadline: .now()) {
                sleep(1)
                print("dispatch 3")
            }
            sleep(1)
            print("dispatch 1")
        }

        self.perform(#selector(test1), with: "selector 2", afterDelay: 0)

        DispatchQueue.main.asyncAfter(deadline: .now()) {
            sleep(1)
            print("dispatch 2")
        }

        print("end test")
    }

}

结果输出:

begin test
end test
dispatch 1
dispatch 2
selector 1
selector 2
dispatch 3
dispatch 4 queued by selector 1
dispatch 4 queued by selector 2
selector 3
selector 3
dispatch 4 queued by selector 3
dispatch 4 queued by selector 3

注意事项:

  1. begin testend test 在显示 perform(_:with:afterDelay:) 的任何其他输出之前打印DispatchQueue.main.asyncAfter 排队并稍后运行。
  2. 前两个 DispatchQueueperform 之前运行,即使它们以不同的顺序排队也是如此。
  3. 所有打印相隔一秒,这意味着它们都在同一个队列中运行,等待前一个完成。
  4. dispatch 3 不会跳到 selector 1selector 2 之前,即使它在 dispatch 1 打印。

结论:

  1. Dispatch.main.asyncAfterperform(_:with:afterDelay:) 都将它们的选择器/闭包排队等待稍后执行。由于您在主线程上运行 perform(_:with:afterDelay:),它使用主队列进行调度。
  2. 出于某种(对我而言)未知的原因,Dispatch.main.asyncAfter(0) 调用在 perform(_:with:afterDelay:0) 调用之前排队,当在同一个运行循环中排队。注意:如果在 Dispatch.main.asyncAfter 中添加任何延迟,它将在 perform(_:with:afterDelay:) 之后排队。例如,尝试使用 .now() + .milliseconds(1)
  3. 尽快执行 只是表示它们按队列顺序排队和处理的另一种说法。根据任务在前面队列中花费的时间,在最终处理任务之前可能需要多次运行运行循环。

关于IOS - DispatchQueue.main.asyncAfter(deadline : . now()) 和 perform(_:with:afterDelay:) 之间的区别,延迟为 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52162558/

相关文章:

objective-c - 如何创建 NSInputStream 的子类?

swift - 构建一个小型计时器应用程序,为什么应用程序计时器不会停止两个标签?

ios - HMAC-SHA1 Swift 3 - 403 禁止

ios - 如何根据对应的UIImageView的尺寸来决定1x、2x、3x的图片尺寸?

ios - 在 Swift 4 中显示实时时间标签?

c++ - cocos2dx 3.0 beta2 Button Click函数一次点击调用两次

objective-c - 椭圆形 NSTextField?

objective-c - 如何从 subview 中添加 rightbarbuttonitem

ios - 自定义 UITableviewCell 中的多行标签

ios - 如何使用 UISlider 降低亮度,使其低于用户可用的最低亮度设置?