Swift中Double类型累加异常求助:无法正确累加数值
问题原因及解决办法
核心问题:@State变量声明位置错误
你在Button的点击闭包内部声明@State var keeper : Double = 0.0,这完全违背了SwiftUI的状态管理规则。@State变量必须作为View的顶层属性存在,闭包里的@State会被当作局部变量,每次闭包执行都会重新初始化为0.0,所以你看到的累加后打印值始终是刚初始化的0.0,根本没真正保存累加结果。
修复步骤
- 将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) } } } } } } } }
主线程更新状态:HealthKit的查询回调运行在后台队列,SwiftUI要求所有@State修改必须在主线程完成,否则会出现状态更新不生效或线程异常,所以要用
DispatchQueue.main.async包裹累加操作。安全处理可选值:把
startDate!换成guard let,避免日期计算失败时触发崩溃。重置累加变量:每次点击refresh按钮时先将keeper重置为0,防止多次点击重复累加历史数值。
内容的提问来源于stack exchange,提问作者Eddie Gabriel
相关产品推荐
相关产品推荐

