在"for in loop"中使用延迟DispatchQueue. [英] Using delay DispatchQueue in "for in loop"

查看:73
本文介绍了在"for in loop"中使用延迟DispatchQueue.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任务是每秒更改背景颜色一次.被用于"for in loop".为了延迟,使用了DispatchQueue.一切似乎都很好,但要注意的是,经过10次迭代后,背景颜色开始以2秒的延迟变化,在3秒后稍有变化.迭代次数越多,延迟越大.我在控制台中显示了时间(以秒为单位)以查看其变化.我看到了结果,但是我不明白哪里出了问题.我通过计时器完成了任务,没有问题,但是我想了解DispatchQueue延迟出了什么问题.

The task is to change the background color once a second. Was used "for in loop". For delay, a DispatchQueue was used. Everything seems to be fine, but it was noticed that after 10 iterations, the background color begins to change with a delay of 2 seconds, a little later in 3 seconds. The more iterations, the greater the delay. I displayed time in the console (seconds) to see how it changes. I see the results, but I do not understand what is wrong. I did the task through a timer, there were no problems, but I want to understand what is wrong with the DispatchQueue delay.

for i in 1...150 {

    DispatchQueue.main.asyncAfter(deadline: .now() + Double(i)) {

        self.view.backgroundColor = UIColor(red: .random(in: 0...1),
                                          green: .random(in: 0...1), 
                                           blue: .random(in: 0...1), 
                                          alpha: 1)
         print("\(ymd)")

         ymd = self.myCalendar.dateComponents([.second], from: Date())
    }
}

控制台:

second: 21 isLeapMonth: false 
second: 21 isLeapMonth: false 
second: 22 isLeapMonth: false 
second: 23 isLeapMonth: false 
second: 24 isLeapMonth: false 
second: 25 isLeapMonth: false 
second: 26 isLeapMonth: false 
second: 27 isLeapMonth: false 
second: 28 isLeapMonth: false 
second: 29 isLeapMonth: false 
second: 30 isLeapMonth: false 
second: 32 isLeapMonth: false 
second: 33 isLeapMonth: false 
second: 33 isLeapMonth: false 
second: 35 isLeapMonth: false 
second: 35 isLeapMonth: false 
second: 37 isLeapMonth: false 
second: 37 isLeapMonth: false 
second: 39 isLeapMonth: false 
second: 39 isLeapMonth: false 
second: 41 isLeapMonth: false 
second: 41 isLeapMonth: false 
second: 44 isLeapMonth: false 
second: 44 isLeapMonth: false 
second: 44 isLeapMonth: false 
second: 47 isLeapMonth: false 
second: 47 isLeapMonth: false 
second: 47 isLeapMonth: false 
second: 50 isLeapMonth: false 
second: 50 isLeapMonth: false 
second: 50 isLeapMonth: false 
second: 54 isLeapMonth: false 
second: 54 isLeapMonth: false 
second: 54 isLeapMonth: false 
second: 57 isLeapMonth: false 
second: 57 isLeapMonth: false 
second: 57 isLeapMonth: false 
second: 57 isLeapMonth: false 
second: 1 isLeapMonth: false 
second: 1 isLeapMonth: false 
second: 1 isLeapMonth: false 
second: 1 isLeapMonth: false 
second: 6 isLeapMonth: false 
second: 6 isLeapMonth: false 
second: 6 isLeapMonth: false 
second: 6 isLeapMonth: false 
second: 6 isLeapMonth: false 
second: 11 isLeapMonth: false 
second: 11 isLeapMonth: false 
second: 11 isLeapMonth: false 
second: 11 isLeapMonth: false 
second: 11 isLeapMonth: false 
second: 17 isLeapMonth: false 
second: 17 isLeapMonth: false 
second: 17 isLeapMonth: false 
second: 17 isLeapMonth: false 
second: 17 isLeapMonth: false 

推荐答案

这是计时器合并"的结果,其中已调度块的余地"为延迟的10%,最大为1一分钟的余地.(这是埋在libdispatch代码中.)这是一项省电功能,可将/组远距离的,独立调度的任务合并在一起同时运行,以避免不必要的硬件过度旋转.避免这种合并的最简单方法是使用重复计时器:

This is a result of "timer coalescing", in which the "leeway" for the dispatched block is 10% of the delay, up to a max of one minute of leeway. (This is buried in the libdispatch code.) It’s a power saving feature to coalesce/group distant, independently scheduled tasks to run at the same time to avoid unnecessary spinning up the hardware too many times. The easiest way to avoid this coalescing is to use a repeating timer:

var counter = 0

Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] timer in
    counter += 1

    guard let self = self, counter <= 150 else {
        timer.invalidate()
        return
    }

    self.view.backgroundColor = UIColor(red: .random(in: 0...1),
                                      green: .random(in: 0...1),
                                       blue: .random(in: 0...1),
                                      alpha: 1)

    let ymd = self.myCalendar.dateComponents([.second], from: Date())
    print(ymd)
}

请注意使用 [弱自我] 模式,以避免让计时器保留对视图控制器的持久引用.并使用该 guard 语句,如果关闭了视图控制器,我们将使计时器 invalidate (计时器).

Note the use of the [weak self] pattern, to avoid having the timer keep a persistent reference to the view controller. And with that guard statement, we’ll invalidate the timer if the view controller is dismissed.

顺便说一句,如果您想使颜色变化不那么刺耳,请为变化设置动画:

BTW, if you want to make the color change less jarring, animate the change:

var counter = 0

Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] timer in
    counter += 1
    guard let self = self, counter <= 150 else {
        timer.invalidate()
        return
    }

    UIView.animate(withDuration: 0.1) {
        self.view.backgroundColor = UIColor(red: .random(in: 0...1),
                                          green: .random(in: 0...1),
                                           blue: .random(in: 0...1),
                                          alpha: 1)
    }

    ...
}

这篇关于在"for in loop"中使用延迟DispatchQueue.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆