Apple HealthKit心率趋势监测定时器启动问题求助
定时器不运行的解决方案
你当前使用的Timer.scheduledTimer在SwiftUI环境中可能因RunLoop绑定问题无法正常触发,建议改用Combine框架的Timer.publish实现定时任务,更适配SwiftUI的响应式生命周期:
修改代码如下:
import Combine @Published var heartRateDirection: Int = 0 private var getHeartRateTrendTimerCancellable: AnyCancellable? func startGetHeartRateTimer() { getHeartRateTrendTimerCancellable = Timer.publish(every: 5, on: .main, in: .common) .autoconnect() .sink { [weak self] _ in self?.heartRateTrendUpOrDown() } } // 在视图消失或对象销毁时取消定时器,避免内存泄漏 func stopGetHeartRateTimer() { getHeartRateTrendTimerCancellable?.cancel() }
同时在视图中补充onDisappear逻辑:
Group{ if resting{ let minutes = currentRestTime / 60 let remainingSeconds = currentRestTime % 60 Text(String(format: "%02d:%02d", minutes, remainingSeconds)) .font(.title3) .bold() .foregroundColor(.green) }else{ Image(systemName: "figure.strengthtraining.traditional") .foregroundColor(.red) .frame(height: 15) } }.onAppear{ workoutManager.startGetHeartRateTimer() }.onDisappear{ workoutManager.stopGetHeartRateTimer() }
代码优化建议
作为Swift新手,以下几个优化点能让你的代码更健壮、可读性更强:
- 用枚举替代魔法数字
把表示心率方向的Int换成枚举,避免无意义的数字赋值,代码逻辑更清晰:
enum HeartRateDirection: Int { case flat = 0 case up = 1 case down = -1 } @Published var heartRateDirection: HeartRateDirection = .flat
后续判断时直接用heartRateDirection == .up这类写法即可。
- 用平均心率替代求和判断趋势
直接求和会受样本数值波动影响,改用平均值判断趋势更准确,还可设置阈值过滤微小波动:
func heartRateTrendUpOrDown() { // 先检查数据是否足够,避免无效计算 guard heartRateData.count >= 6 else { print("心率数据不足6条,无法判断趋势") return } let last6 = heartRateData.suffix(6) let first3Values = last6.prefix(3).map { $0.value } let last3Values = last6.suffix(3).map { $0.value } let avgFirst3 = first3Values.reduce(0, +) / Double(first3Values.count) let avgLast3 = last3Values.reduce(0, +) / Double(last3Values.count) // 设置阈值,忽略微小波动 let fluctuationThreshold = 1.0 if abs(avgFirst3 - avgLast3) < fluctuationThreshold { print("Staying Flat") heartRateDirection = .flat } else if avgFirst3 < avgLast3 { handleUpTrend() } else { handleDownTrend() } } // 拆分趋势处理逻辑,让主函数更简洁 private func handleUpTrend() { if heartRateDirection == .up { print("Continuing to Go Up") } else { resting = false stopRestTimer() heartRateDirection = .up print("first time going up") } } private func handleDownTrend() { if heartRateDirection == .down { print("Continuing to Go Down") } else { resting = true startRestTimer() heartRateDirection = .down print("first time going down") } }
增加数据合法性检查
在计算趋势前先判断heartRateData的样本数量,避免数组越界或无效计算。使用弱引用避免内存泄漏
在闭包中始终使用[weak self],防止定时器或其他闭包持有对象导致内存泄漏。
内容的提问来源于stack exchange,提问作者Conmans
相关产品推荐
相关产品推荐

