在 "for in loop" 中使用延迟 DispatchQueue
Using delay DispatchQueue in "for in loop"
任务是每秒改变一次背景颜色。被使用 "for in loop"。对于延迟,使用了 DispatchQueue。一切似乎都很好,但注意到在 10 次迭代后,背景颜色开始变化,延迟 2 秒,稍晚 3 秒。迭代次数越多,延迟越大。我在控制台中显示时间(秒)以查看它是如何变化的。我看到了结果,但我不明白哪里出了问题。我是通过timer做的任务,没有问题,但是我想了解DispatchQueue延迟有什么问题。
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%,最多一分钟的余地。 (这是 buried in the libdispatch code。)这是一项节能功能,可以同时将 coalesce/group 远距离、独立计划的任务 运行,以避免不必要地多次启动硬件。避免这种合并的最简单方法是使用重复计时器:
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)
}
注意 [weak self]
模式的使用,以避免让计时器保持对视图控制器的持久引用。使用那个 guard
语句,如果视图控制器被关闭,我们将 invalidate
计时器。
顺便说一句,如果您想让颜色变化不那么刺耳,请为变化设置动画:
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。一切似乎都很好,但注意到在 10 次迭代后,背景颜色开始变化,延迟 2 秒,稍晚 3 秒。迭代次数越多,延迟越大。我在控制台中显示时间(秒)以查看它是如何变化的。我看到了结果,但我不明白哪里出了问题。我是通过timer做的任务,没有问题,但是我想了解DispatchQueue延迟有什么问题。
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%,最多一分钟的余地。 (这是 buried in the libdispatch code。)这是一项节能功能,可以同时将 coalesce/group 远距离、独立计划的任务 运行,以避免不必要地多次启动硬件。避免这种合并的最简单方法是使用重复计时器:
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)
}
注意 [weak self]
模式的使用,以避免让计时器保持对视图控制器的持久引用。使用那个 guard
语句,如果视图控制器被关闭,我们将 invalidate
计时器。
顺便说一句,如果您想让颜色变化不那么刺耳,请为变化设置动画:
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)
}
...
}