Swift变量未更新问题:如何让函数返回修改后的returnVal?
问题分析与解决
你的问题核心是异步操作的执行顺序:makeQuery是异步方法(HealthKit查询在后台线程执行,通过逃逸闭包返回结果),而RecieveActivitySummary是同步返回值的函数。函数执行时会先跑完return returnVal,之后异步闭包才会触发修改returnVal,所以返回的自然是初始的空对象。
解决方法:把RecieveActivitySummary改成异步回调形式
同步函数无法等待异步任务完成再返回结果,所以必须将RecieveActivitySummary改为通过闭包回调返回HKActivitySummary,而不是直接返回值。
修改后的代码
// 改成带逃逸闭包的异步函数 func receiveActivitySummary(completion: @escaping (HKActivitySummary) -> Void) { self.makeQuery() { (summary) in // 拿到结果后通过闭包返回 completion(summary) print(summary) // 这里打印的是带数据的对象 } } // 原makeQuery函数可以保持不变(如果没有其他问题的话) func makeQuery(completion: @escaping (_ summary : HKActivitySummary) -> ()) { let calendar = NSCalendar.current let endDate = Date() guard let startDate = calendar.date(byAdding: .day, value: 0, to: endDate) else { fatalError("error") } let units: Set<Calendar.Component> = [.day, .month, .year, .era] var startDatecomps = calendar.dateComponents(units, from: startDate) startDatecomps.calendar = calendar var endDatecomps = calendar.dateComponents(units, from: endDate) endDatecomps.calendar = calendar let summariesWithinRange = HKQuery.predicate(forActivitySummariesBetweenStart: startDatecomps, end: endDatecomps) let query = HKActivitySummaryQuery(predicate: summariesWithinRange) { (sample, results, error) -> Void in if let results = results { var summary = results[0] completion(summary) } } healthstore.execute(query) }
调用方式
// 调用时通过闭包接收结果 receiveActivitySummary { summary in // 在这里处理拿到的HKActivitySummary对象 print("拿到的结果:\(summary)") }
额外提醒
- 注意处理
makeQuery中可能的错误情况(比如results为空、error不为空的情况),避免崩溃。可以在HKActivitySummaryQuery的回调里加上错误判断:
let query = HKActivitySummaryQuery(predicate: summariesWithinRange) { (sample, results, error) -> Void in if let error = error { // 处理错误,比如打印错误信息或者通过闭包返回错误 print("查询失败:\(error.localizedDescription)") return } guard let results = results, !results.isEmpty else { print("没有找到活动数据") return } var summary = results[0] completion(summary) }
内容的提问来源于stack exchange,提问作者Eddie Gabriel
相关产品推荐
相关产品推荐

