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

Swift中Double类型累加异常求助:无法正确累加数值

问题原因及解决办法

核心问题:@State变量声明位置错误

你在Button的点击闭包内部声明@State var keeper : Double = 0.0,这完全违背了SwiftUI的状态管理规则。@State变量必须作为View的顶层属性存在,闭包里的@State会被当作局部变量,每次闭包执行都会重新初始化为0.0,所以你看到的累加后打印值始终是刚初始化的0.0,根本没真正保存累加结果。

修复步骤

  1. 将keeper移到ContentView的属性区,和其他@State变量放在同一层级:
struct ContentView: View {
    @StateObject var fitness = main()
    @State var final = HKActivitySummary()
    @State var WeekElevation = 0.0
    @State var keeper : Double = 0.0 // 移至此处
    
    var body: some View {
        Button("refresh"){
            fitness.authorizeHealthkit()
            fitness.makeQuery() { (summary) in
                final = summary
            }
            // 删除闭包内的@State声明
            fitness.makeElevationQuery { statisticsCollection in
                if let statisticsCollection = statisticsCollection {
                    // 安全解包起始日期,避免强制解包崩溃
                    guard let startDate = Calendar.current.date(byAdding: .weekOfYear, value: -1, to: Date()) else {
                        print("无法计算起始日期")
                        return
                    }
                    let endDate = Date()
                    // 每次查询前重置keeper,避免重复累加
                    keeper = 0.0
                    statisticsCollection.enumerateStatistics(from: startDate, to: endDate) {
                        (statistics, stop) in
                        if let count = statistics.sumQuantity()?.doubleValue(for: .count()) {
                            print(count)
                            // HealthKit回调在后台线程,必须切主线程更新@State
                            DispatchQueue.main.async {
                                keeper += count
                                print(keeper)
                            }
                        }
                    }
                }
            }
        }
    }
}
  1. 主线程更新状态:HealthKit的查询回调运行在后台队列,SwiftUI要求所有@State修改必须在主线程完成,否则会出现状态更新不生效或线程异常,所以要用DispatchQueue.main.async包裹累加操作。

  2. 安全处理可选值:把startDate!换成guard let,避免日期计算失败时触发崩溃。

  3. 重置累加变量:每次点击refresh按钮时先将keeper重置为0,防止多次点击重复累加历史数值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 08:45:28