Swift异步步数查询函数封装需求:简化调用,错误时返回0
如何同步获取健康Kit步数(错误时返回0)
原函数是异步函数,通过completion闭包返回结果,因此无法直接用steps = getStepCountForDayXDaysAgo(4)的同步方式调用。要实现你想要的效果,有两种可行方案:
方案1:使用Swift 5.5+的Async/Await(推荐)
通过withCheckedThrowingContinuation将原异步函数包装为支持async/await的同步风格函数,同时处理错误返回0:
// 包装原函数为Async/Await版本 func getStepCountForDayXDaysAgo(_ daysAgo: Int) async -> Double { await withCheckedThrowingContinuation { continuation in // 调用原异步函数 getStepCountForDayXDaysAgo(daysAgo) { steps, error in // 错误或无结果时返回0,否则返回步数 continuation.resume(returning: steps ?? 0) } } }
调用方式
需要在异步上下文中调用(比如Task内部):
Task { let steps = await getStepCountForDayXDaysAgo(4) // 直接使用steps,失败时自动返回0 print("步数:\(steps)") }
方案2:使用信号量(兼容老版本Swift)
通过DispatchSemaphore阻塞当前线程等待异步结果,适合Swift 5.5之前的版本:
func getStepCountForDayXDaysAgo(_ daysAgo: Int) -> Double { let semaphore = DispatchSemaphore(value: 0) var finalSteps: Double = 0 getStepCountForDayXDaysAgo(daysAgo) { steps, error in finalSteps = steps ?? 0 semaphore.signal() // 通知信号量结束等待 } semaphore.wait() // 阻塞线程直到异步回调完成 return finalSteps }
调用方式
可以直接同步调用,但注意不要在主线程使用(会导致UI卡死):
// 建议在后台队列调用 DispatchQueue.global().async { let steps = getStepCountForDayXDaysAgo(4) print("步数:\(steps)") // 如果需要更新UI,切回主线程 DispatchQueue.main.async { // 更新UI逻辑 } }
注意事项
- Async/Await是Swift官方推荐的并发方案,代码更简洁且不会阻塞线程,优先使用
- 信号量方式会阻塞当前线程,滥用可能导致性能问题或死锁,仅用于老版本兼容场景
内容的提问来源于stack exchange,提问作者user793174
相关产品推荐
相关产品推荐

