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

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新手,以下几个优化点能让你的代码更健壮、可读性更强:

  1. 用枚举替代魔法数字
    把表示心率方向的Int换成枚举,避免无意义的数字赋值,代码逻辑更清晰:
enum HeartRateDirection: Int {
    case flat = 0
    case up = 1
    case down = -1
}

@Published var heartRateDirection: HeartRateDirection = .flat

后续判断时直接用heartRateDirection == .up这类写法即可。

  1. 用平均心率替代求和判断趋势
    直接求和会受样本数值波动影响,改用平均值判断趋势更准确,还可设置阈值过滤微小波动:
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")
    }
}
  1. 增加数据合法性检查
    在计算趋势前先判断heartRateData的样本数量,避免数组越界或无效计算。

  2. 使用弱引用避免内存泄漏
    在闭包中始终使用[weak self],防止定时器或其他闭包持有对象导致内存泄漏。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 22:07:28