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

Swift/HealthKit应用:如何用Task替代已弃用的Semaphore?

问题原因及解决方案

你的Task实现返回0的核心问题是:HK查询是异步执行的,但你的Task在调用healthStore.execute(query)后立刻返回了初始值0,此时查询的闭包还没来得及执行,goal根本没被赋值。

要将基于闭包的HealthKit查询适配到async/await模式,正确的做法是用withCheckedContinuation(或withCheckedThrowingContinuation处理错误)把回调式API包装成异步函数。以下是修正后的代码:

func getMoveGoal() async throws -> Int {
    let calendar = Calendar.current
    var startDateComponents = calendar.dateComponents([.year, .month, .day], from: Date())
    startDateComponents.calendar = calendar
    
    let predicate = HKQuery.predicateForActivitySummary(with: startDateComponents)
    
    return try await withCheckedThrowingContinuation { continuation in
        let query = HKActivitySummaryQuery(predicate: predicate) { _, summariesOrNil, errorOrNil in
            // 处理错误
            if let error = errorOrNil {
                continuation.resume(throwing: error)
                return
            }
            
            // 提取目标值
            guard let summaries = summariesOrNil, let firstSummary = summaries.first else {
                continuation.resume(returning: 0) // 无数据时返回0,或根据需求抛错
                return
            }
            
            let goal = Int(firstSummary.activeEnergyBurnedGoal.doubleValue(for: .kilocalorie()))
            continuation.resume(returning: goal)
        }
        
        healthStore.execute(query)
    }
}

关键说明:

  • withCheckedContinuation会暂停当前任务,直到我们调用continuation.resume(),这样就能等待HK查询的闭包执行完成后再返回结果。
  • 必须确保continuation.resume()只被调用一次,否则会引发运行时崩溃,所以要在错误、无数据、成功赋值等所有分支都处理到。
  • 改用throws可以把HealthKit的查询错误抛出去,让调用方处理,比直接返回0更严谨。

调用示例:

在SwiftUI视图或其他异步上下文里调用时,用await:

Task {
    do {
        let moveGoal = try await getMoveGoal()
        print("获取到的Move目标:\(moveGoal)")
        // 在这里使用目标值进行后续计算
    } catch {
        print("查询失败:\(error)")
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 06:14:58