gpt4 book ai didi

ios - 如何最好地确保在触发完成处理程序之前我拥有所有数据?

转载 作者:行者123 更新时间:2023-11-28 05:54:37 25 4
gpt4 key购买 nike

我对如何最好地获取我的 HealthKit 数据感到困惑,尤其是心率记录。我的问题是由于竞争条件引起的,这是由于异步调用和完成处理程序引起的。

我的应用程序会记录一次锻炼,并最终将该数据推送到远程服务器以进行清理和分析。我想在 session 同步请求中包含心率数据。

一次训练由 GPS 和其他分成几圈的传感器数据组成。

当我开始同步 session 时,我会像这样调用以下函数:

fetchSessionLapTimes(session: session) { (storedSessionLapTime, error) in
//handle the received lap time data
//At this point, I expect my storedSessionLapTime variable to
//contain my session lap times, and heart rate data
})

我的 fetchSessionLapTimes 函数定义如下:

func fetchSessionLapTimes(session: Session, withCompletion complete: ((_ storedSessionLapTime: [SessionLapTime], _ error: Error?) -> Void)!) {
var storedSessionLapTime = [SessionLapTime]()

managedObjectContext.performAndWait {
//get session lap times from Core Data
//this code works fine, as expected and populates
//storedSessionLapTime
}

//now this is where my problem is. At this point I want to extract
//heart rate data for each lap time

let healthStoreService = HealthStoreService()
for sessionLapTime in storedSessionLapTime {
let start = Date(timeIntervalSince1970: sessionLapTime.lapStartDate)
let end = Date(timeIntervalSince1970: sessionLapTime.lapEndDate)

healthStoreService.fetchWorkoutData(startDate: start, endDate: end) { (success, error) in
complete(storedSessionLapTime, nil)
}
}
}

我的fetchSessionLapTimes函数定义如下:

func fetchWorkoutData(startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: Error?) -> Void)!) {
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: .strictStartDate)

let query = HKSampleQuery(sampleType: hrType, predicate: predicate, limit: Int(HKObjectQueryNoLimit), sortDescriptors: nil) {
query, results, error in

guard let samples = results as? [HKQuantitySample] else {
completion(false, error)
fatalError("Error fetching workout data: \(error!.localizedDescription)");
}

if samples.count < 1 {
self.debug.log(tag: "HealthStoreService", content: "No workout data found")
completion(true, nil)
return
}

DispatchQueue.main.async {
for sample in samples {
self.debug.log(tag: "HealthStoreService", content: "\(sample.quantity.doubleValue(for: self.hrUnit))")
}

completion(true, nil)
return
}
}

healthStore.execute(query)
}

如您所见,此函数也是异步的。如果我运行这段代码,我不会取回所有圈数的心率数据。 在允许 fetchSessionLapTimes 返回之前,如何确保我拥有所有圈数的心率数据?

最佳答案

您可以将 for 循环中的所有 fetchWorkoutData 任务添加到 DispatchGroup。当所有这些都完成时,您会收到通知,因此您可以调用完成函数。这是一个例子:

func fetchSessionLapTimes(session: Session, withCompletion complete: ((_ storedSessionLapTime: [SessionLapTime], _ error: Error?) -> Void)!) {
var storedSessionLapTime = [SessionLapTime]()

managedObjectContext.performAndWait {
//
}

// Here you were putting async calls to a for loop and couldn't tell when all were completed
// DispatchGroup is made exactly to handle this
let dispatchGroup = DispatchGroup()
let healthStoreService = HealthStoreService()
for sessionLapTime in storedSessionLapTime {
let start = Date(timeIntervalSince1970: sessionLapTime.lapStartDate)
let end = Date(timeIntervalSince1970: sessionLapTime.lapEndDate)

// Adding the task to group
dispatchGroup.enter()
healthStoreService.fetchWorkoutData(startDate: start, endDate: end) { (success, error) in
// notifying when this particular task finishes
dispatchGroup.leave()
}
}

// completion is called only when all of the DispatchGroup tasks are finished
dispatchGroup.notify(queue: .main) {
// call completion here because all tasks completed
complete(storedSessionLapTime, nil)
}
}

关于ios - 如何最好地确保在触发完成处理程序之前我拥有所有数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51834672/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com