SwiftUI DispatchQueue asyncAfter在完成十个计划任务后停止正常工作

SwiftUI DispatchQueue asyncAfter在完成十个计划任务后停止正常工作,swift,swiftui,grand-central-dispatch,Swift,Swiftui,Grand Central Dispatch,如果我运行下面的代码,它将正确计数为10,然后跳过每个奇数 如果让它运行超过20,它将开始越来越多地跳过(输出将类似于1-2-3-4-5-6-7-8-9-10-12-14-16-18-20-23-26-29…) 找不到文档,例如计划任务的限制,因此询问您:) 从昨天开始学习SwiftUI,如果这是一个明显的问题,请原谅 如果它被安排在与main不同的DispatchQueue中,则没有区别 谢谢你的帮助 import SwiftUI struct ContentView: View {

如果我运行下面的代码,它将正确计数为10,然后跳过每个奇数

如果让它运行超过20,它将开始越来越多地跳过(输出将类似于1-2-3-4-5-6-7-8-9-10-12-14-16-18-20-23-26-29…)

找不到文档,例如计划任务的限制,因此询问您:) 从昨天开始学习SwiftUI,如果这是一个明显的问题,请原谅

如果它被安排在与main不同的DispatchQueue中,则没有区别

谢谢你的帮助

import SwiftUI

struct ContentView: View {
    @State private var counter : Int = 0
    
    func buttonTap() {
        let time : DispatchTime = .now()
        
        var delay : Double = 0
        
        for _ in 1...50 {
            
            delay = delay + 0.2
            
            DispatchQueue.main.asyncAfter(deadline: time + delay) {
                counter += 1
            }
            
        }
    }
    
    var body: some View {
        ZStack {
            
            Color(.black)
                .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
            
            Text(String(counter))
                .foregroundColor(.green)
                .padding()
            
            Text("Button")
                .foregroundColor(.green)
                .offset(y: 50)
                .onTapGesture(perform: {
                    buttonTap()
                })
            
        }
    }
}

这是一种奇怪的行为,它甚至会在事件之间出现更长的时间间隔(例如,2秒)

考虑改用
计时器

您可以使用多个单一火灾计时器,其工作方式与您的单独调度相同:

func buttonTap() {
    
    var delay : Double = 0
    
    for _ in 1...50 {
        
        delay = delay + 0.2
        
        Timer.scheduledTimer(withTimeInterval: delay, repeats: false) { timer in
            self.counter += 1
        }
        
    }
}
或者每
0.2
秒触发一个计时器:

func buttonTap() {
    Timer.scheduledTimer(withTimeInterval: 0.2, repeats: true) { timer in
        self.counter += 1
        if counter == 50 {
            timer.invalidate()
        }
    }
}

这是一种奇怪的行为,它甚至会在事件之间出现更长的时间间隔(例如,2秒)

考虑改用
计时器

您可以使用多个单一火灾计时器,其工作方式与您的单独调度相同:

func buttonTap() {
    
    var delay : Double = 0
    
    for _ in 1...50 {
        
        delay = delay + 0.2
        
        Timer.scheduledTimer(withTimeInterval: delay, repeats: false) { timer in
            self.counter += 1
        }
        
    }
}
或者每
0.2
秒触发一个计时器:

func buttonTap() {
    Timer.scheduledTimer(withTimeInterval: 0.2, repeats: true) { timer in
        self.counter += 1
        if counter == 50 {
            timer.invalidate()
        }
    }
}

这种行为被称为计时器合并,在这种情况下,相互间隔不超过10%的独立计划事件将合并在一起,并同时运行。这是一种省电功能

有多种解决方案可避免凝聚:

  • 使用重复计时器
  • 在前一个迭代的完成处理程序中安排每个迭代;或
  • 创建“严格”的GCD计时器,它不会被合并

重复计时器是最常见的解决方案。

这种行为称为计时器合并,在这种情况下,发生在彼此10%以内的独立计划事件将合并在一起,并同时运行。这是一种省电功能

有多种解决方案可避免凝聚:

  • 使用重复计时器
  • 在前一个迭代的完成处理程序中安排每个迭代;或
  • 创建“严格”的GCD计时器,它不会被合并

重复计时器是最常见的解决方案。

我在这里没有看到任何缺陷-计数器的更新速度比UI快,所以您不会看到所有情况。你为什么要这样做?我正在制作一个呼吸冥想应用程序,它有几秒钟的延迟…但是,例如,它只是超过了几秒钟的暂停时间,直接开始下一个任务…不要认为,这是因为缓慢的UI更新?还是这样?即使在更复杂的应用程序中,问题也会在十个任务后出现。我在这里看不到任何缺陷-计数器的更新速度比UI快,所以您不会看到所有情况。你为什么要这样做?我正在制作一个呼吸冥想应用程序,它有几秒钟的延迟…但是,例如,它只是超过了几秒钟的暂停时间,直接开始下一个任务…不要认为,这是因为缓慢的UI更新?还是这样?即使在更复杂的应用程序中,问题也会在完成十项任务后出现。非常感谢,它是这样工作的!是否允许我将您的问题标记为解决方案(因为它显示了另一种方式,并且没有解释DispatchQueue行为)?是的,作为问题作者,您可以将任何答案标记为您认为合适的解决方案。如果有更好的答案出现,你也可以更改被接受的答案,这样它就不会一成不变了。非常感谢,它是这样工作的!是否允许我将您的问题标记为解决方案(因为它显示了另一种方式,并且没有解释DispatchQueue行为)?是的,作为问题作者,您可以将任何答案标记为您认为合适的解决方案。如果有更好的答案出现,你也可以修改被接受的答案,这样它就不会一成不变了。