SwiftUI技术咨询:如何实现点击按钮后数值按步长1定时递增至目标增量
SwiftUI实现数值逐次递增动画
你的代码存在逻辑问题:jackpot()里的while循环是同步执行的,会瞬间生成10000个延迟0.01秒的异步任务,这些任务几乎同时触发,导致creditScore直接跳变,看不到逐个递增的动画效果;而且循环结束后立刻重置count,会打乱计数逻辑。
以下是两种可行的解决方案:
方案一:递归异步调用
通过递归方式,每次完成一次递增后再触发下一次延迟递增,确保每次递增间隔0.01秒:
import SwiftUI struct TestView: View { @State var creditScore: Int = 5000 @State var currentIncrement: Int = 0 let targetIncrement: Int = 10000 let interval: TimeInterval = 0.01 var body: some View { VStack { Text("\(creditScore)") .font(.largeTitle) Button("deal") { startIncrement() } .buttonStyle(.borderedProminent) } } func startIncrement() { currentIncrement = 0 incrementStep() } func incrementStep() { guard currentIncrement < targetIncrement else { return } currentIncrement += 1 creditScore += 1 DispatchQueue.main.asyncAfter(deadline: .now() + interval) { incrementStep() } } }
方案二:使用Timer
通过Timer定时触发递增,达到目标后停止Timer:
import SwiftUI struct TestView: View { @State var creditScore: Int = 5000 @State var currentIncrement: Int = 0 let targetIncrement: Int = 10000 let interval: TimeInterval = 0.01 @State private var timer: Timer? var body: some View { VStack { Text("\(creditScore)") .font(.largeTitle) Button("deal") { startIncrement() } .buttonStyle(.borderedProminent) } .onDisappear(perform: stopTimer) } func startIncrement() { timer?.invalidate() currentIncrement = 0 timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { [weak self] timer in guard let self = self else { timer.invalidate() return } if self.currentIncrement < self.targetIncrement { self.currentIncrement += 1 self.creditScore += 1 } else { timer.invalidate() self.timer = nil } } } func stopTimer() { timer?.invalidate() timer = nil } }
额外说明
- 遵循Swift命名规范:视图结构体用大驼峰命名(如
TestView),变量名用小驼峰; - 无需修改的常量用
let声明,减少可变状态; - 字符串插值
"\(creditScore)"比String(creditScore)更简洁; - 方案二中使用
[weak self]避免循环引用,onDisappear中停止Timer防止内存泄漏。
内容的提问来源于stack exchange,提问作者George T
相关产品推荐
相关产品推荐

