Swift:主线程for循环中使用DispatchTime及延迟未触发问题求助
Swift中主线程循环里使用DispatchTime的正确姿势
咱先拆解下你遇到的问题:你这段代码其实不是没触发执行,而是所有的打印任务会在差不多同一时间全部跑起来,导致你误以为延迟没生效~
为啥会这样?因为你的for循环是在主线程同步执行的,10001次循环几乎是瞬间完成的——每一次循环都立刻计算了deadLine = now() + 1秒,然后把这个任务扔进主线程的调度队列里。所以所有任务的执行时间都是当前时间+1秒,等这个时间到了,它们就会扎堆执行,自然看不到你想要的“每隔1秒打印一个数字”的效果。
正确的实现方式
我之前做类似的定时序列任务时,常用两种方法:
方法1:递归调用(简单直观)
通过递归的方式,每次完成当前任务后再调度下一次,保证任务按顺序间隔执行:
func printSequentially(start: Int, end: Int, delay: TimeInterval = 1.0) { guard start <= end else { return } DispatchQueue.main.asyncAfter(deadline: .now() + delay) { print(start) // 递归调度下一个任务 self.printSequentially(start: start + 1, end: end, delay: delay) } } // 调用示例 printSequentially(start: 0, end: 10000)
这个方法的好处是逻辑简单,容易理解,适合任务数量不多的场景。
方法2:用DispatchSourceTimer(高效精准)
如果任务数量很大(比如你这里的10000次),用DispatchSourceTimer会更高效,它本质是一个定时器,能精准控制重复执行的间隔:
func printWithTimer(totalCount: Int, interval: TimeInterval = 1.0) { var currentIndex = 0 // 创建主线程队列的定时器 let timer = DispatchSource.makeTimerSource(queue: .main) // 设置定时器:立刻开始,每隔interval秒重复一次 timer.schedule(deadline: .now(), repeating: interval) timer.setEventHandler { print(currentIndex) currentIndex += 1 // 达到次数后取消定时器 if currentIndex > totalCount { timer.cancel() } } // 启动定时器 timer.resume() } // 调用示例 printWithTimer(totalCount: 10000)
这种方式不会一次性创建大量的异步任务,对主线程的压力更小,执行也更精准。
额外提醒
如果你的需求只是在主线程每隔一段时间执行任务,尽量避免在循环里批量提交asyncAfter——不仅会导致任务扎堆,还可能因为短时间内创建大量任务,让主线程的调度队列出现拥堵,影响UI响应。
内容的提问来源于stack exchange,提问作者Manikandan S
相关产品推荐
相关产品推荐

