You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI长按手势数字递增,释放后Timer未停止问题求助

长按步进器释放后Timer无法停止的解决方法

问题场景

实现长按手势触发数字快速递增的步进器,目前长按能正常触发递增,但释放手势后Timer仍在运行,数字持续增加。

原代码

struct CustomFoodItemView: View {
    @State var foodName = ""
    @State var proteinAmount = 1
    @State var carbAmount = 1
    @State var fatAmount = 1
    
    @State private var timer: Timer?
    @State var isLongPressing = false
    
    var body: some View {
        VStack{
            
            VStack{
                Text("Food Name")
                TextField("", text: $foodName)
                    .multilineTextAlignment(.center)
                    .border(.white)
                    .padding(.trailing, 10)
                    .frame(width:100, height:10)
            }
            HStack{
                Text(String(proteinAmount) + "g")
                    .frame(width:50, height:50)
                
                Image(systemName: "plus.circle.fill")
                    .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 30, height: 30)
                        .foregroundColor(Color("SuccessButtonColor"))
                        .simultaneousGesture(LongPressGesture(minimumDuration: 0.2).onChanged { _ in
                                      print("long press")
                                      self.isLongPressing = true
                            if self.isLongPressing == true{
                                self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in
                                    proteinAmount += 1
                                })
                            } 
                                  }
                                .onEnded { _ in
                            print("stopped") //why won't you stop
                                    self.isLongPressing = false
                                })
                       }
              }
}

问题原因

  1. 释放手势时仅修改了isLongPressing状态,但没有主动停止并销毁Timer实例,Timer会继续在后台运行
  2. 长按过程中会重复创建多个Timer,导致多组递增逻辑同时执行

修复后的代码

struct CustomFoodItemView: View {
    @State var foodName = ""
    @State var proteinAmount = 1
    @State var carbAmount = 1
    @State var fatAmount = 1
    
    @State private var timer: Timer?
    @State var isLongPressing = false
    
    var body: some View {
        VStack{
            VStack{
                Text("Food Name")
                TextField("", text: $foodName)
                    .multilineTextAlignment(.center)
                    .border(.white)
                    .padding(.trailing, 10)
                    .frame(width:100, height:10)
            }
            HStack{
                Text(String(proteinAmount) + "g")
                    .frame(width:50, height:50)
                
                Image(systemName: "plus.circle.fill")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 30, height: 30)
                    .foregroundColor(Color("SuccessButtonColor"))
                    .simultaneousGesture(
                        LongPressGesture(minimumDuration: 0.2)
                            .onChanged { _ in
                                // 避免重复创建Timer
                                guard !isLongPressing else { return }
                                isLongPressing = true
                                // 创建单次循环Timer
                                timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { _ in
                                    proteinAmount += 1
                                }
                            }
                            .onEnded { _ in
                                isLongPressing = false
                                // 停止Timer并销毁实例
                                timer?.invalidate()
                                timer = nil
                            }
                    )
            }
        }
    }
}

关键修改点

  • 在onChanged中增加判断逻辑,确保同一时间只创建一个Timer,避免重复触发多组递增
  • 在onEnded回调中调用timer?.invalidate()停止Timer,再将timer设为nil彻底释放资源,确保Timer不会继续运行

长按步进器修复效果演示

内容的提问来源于stack exchange,提问作者Swink

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 18:11:00