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 }) } } }
问题原因
- 释放手势时仅修改了
isLongPressing状态,但没有主动停止并销毁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 // 避免重复创建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
相关产品推荐
相关产品推荐

