SwiftUI实现单视图内点击按钮切换锻炼内容,避免计时器异常
单视图内切换健身内容,解决Timer重复调用导致的倒计时异常问题
问题背景
原本通过NavigationPath跳转多视图展示不同锻炼内容,但这种方式会创建多个TimerView实例,导致计时器被多次调用,出现倒计时速度异常加快的问题。现在需要实现在单个视图内通过按钮切换锻炼的标题、视频示例和步骤文本。
修改后的完整代码
import SwiftUI import AVKit // 假设你的数据结构定义如下(如果已存在可忽略): // struct Exercise { // let title: String // let video: AVPlayer // let steps: String // } // struct ExercisePlan { // let exercises: [Exercise] // } struct ExerciseScreenView: View { @Binding var streaks: Streaks @Binding var timerStruct: TimerStruct private let defaultCountdown = 300 @State private var currentExerciseIndex = 0 let exercisePlan: ExercisePlan @Binding var navigationPath: NavigationPath private func resetTimer() { timerStruct.countdownTimer = defaultCountdown timerStruct.timerRunning = false } private func switchToNextExercise() { if currentExerciseIndex < exercisePlan.exercises.count - 1 { currentExerciseIndex += 1 resetTimer() } else { // 所有锻炼完成后返回上一页,可按需修改逻辑 navigationPath.removeLast() } } var body: some View { VStack { Form { Section(header: Text("\(currentExerciseIndex + 1)th Exercise (Scroll down for steps)")) { Text(exercisePlan.exercises[currentExerciseIndex].title) .font(.system(size: 35, weight: .medium)) } Section(header: Text("Video Example")) { VideoPlayer(player: exercisePlan.exercises[currentExerciseIndex].video) .scaledToFit() .frame(alignment: .center) .cornerRadius(10) } Section(header: Text("Steps:")) { Text(exercisePlan.exercises[currentExerciseIndex].steps) .font(.system(size: 20, weight: .regular)) .padding() .frame(alignment: .center) } } TimerView(streaks: $streaks, timerStruct: $timerStruct) .padding(.bottom, 15) Button(action: switchToNextExercise) { Text(currentExerciseIndex < exercisePlan.exercises.count - 1 ? "Next Exercise" : "Finish") .padding() .background(Color(red: 184/255, green: 243/255, blue: 255/255)) .foregroundColor(.black) .cornerRadius(10) } .padding(.horizontal, 10) .padding(.bottom, 10) .navigationBarBackButtonHidden() } } }
核心修改说明
- 用索引控制内容切换:新增
currentExerciseIndex状态变量,通过它动态展示当前锻炼的标题、视频和步骤,彻底避免多视图跳转带来的Timer实例重复问题。 - 切换时重置计时器:每次切换锻炼时调用
resetTimer(),将计时器重置为初始值并停止运行,防止多个计时逻辑叠加导致倒计时过快。 - 动态按钮文本:根据当前是否为最后一个锻炼,自动切换按钮文本为"Next Exercise"或"Finish",提升用户体验。
- 数据适配:假设
ExercisePlan包含一个exercises数组,如果你的原数据结构不同,只需对应调整数组访问的部分即可。
这样修改后,所有锻炼内容都在同一个视图内渲染,不会重复创建Timer相关实例,完美解决倒计时异常的问题。
内容的提问来源于stack exchange,提问作者Zudoturiku
相关产品推荐
相关产品推荐

