Swift 调度组未通知?
我在另一个应用程序中有这个相同的代码,它可以正常工作,现在在这个应用程序中,调度组没有发出通知,我的处理程序也没有被调用?我无法找出这两个应用程序之间的区别,因为代码是相同的Swift 调度组未通知?,swift,grand-central-dispatch,Swift,Grand Central Dispatch,我在另一个应用程序中有这个相同的代码,它可以正常工作,现在在这个应用程序中,调度组没有发出通知,我的处理程序也没有被调用?我无法找出这两个应用程序之间的区别,因为代码是相同的 func getHeartRateMaxFromWorkouts(workouts: [HKWorkout], handler: @escaping (careerMaxHeartRatePerWorkoutAsCustomHistoricalSample, careerAverageHeartRatePerWorkou
func getHeartRateMaxFromWorkouts(workouts: [HKWorkout], handler: @escaping (careerMaxHeartRatePerWorkoutAsCustomHistoricalSample, careerAverageHeartRatePerWorkoutAsCustomHistoricalSample) -> Void) {
let workoutsReversed = workouts.reversed()
guard let heartRateType:HKQuantityType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate) else { return }
let heartRateUnit:HKUnit = HKUnit(from: "count/min")
var heartRateMaxArrayAsCustomHistoricalSample = [CustomHistoricalSample]()
var heartRateAvgArrayAsCustomHistoricalSample = [CustomHistoricalSample]()
//DispatchGroup needed since making async call per workout and need notified when all calls are done
let dispatchGroup = DispatchGroup()
for workout in workoutsReversed {
//predicate
let startDate = workout.startDate
let endDate = workout.endDate
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: .strictStartDate)
//descriptor
let sortDescriptors = [
NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: true) //Changed this to false so that HRR and MCS would calculate, always check this if not getting these values
]
dispatchGroup.enter()
let heartRateQuery = HKSampleQuery(sampleType: heartRateType,
predicate: predicate,
limit: (HKObjectQueryNoLimit),
sortDescriptors: sortDescriptors)
{ (query:HKSampleQuery, results:[HKSample]?, error:Error?) -> Void in
guard error == nil else { print("get heart rate error"); return }
guard let unwrappedResults = results as? [HKQuantitySample] else { print("get heart rate error"); return}
let heartRatesAsDouble = unwrappedResults.map {$0.quantity.doubleValue(for: heartRateUnit)}
guard let max = heartRatesAsDouble.max() else { return }
let maxAsCustomHistoricalSample = CustomHistoricalSample(value: max, date: workout.startDate)
heartRateMaxArrayAsCustomHistoricalSample.append(maxAsCustomHistoricalSample)
let average = heartRatesAsDouble.average
let averageAsCustomHistoricalSample = CustomHistoricalSample(value: average, date: workout.startDate)
heartRateAvgArrayAsCustomHistoricalSample.append(averageAsCustomHistoricalSample)
dispatchGroup.leave()
}
healthStore.execute(heartRateQuery)
} //End of for workout loop
dispatchGroup.notify(queue: .main) {
//Need to sort by date since the dates come back jumbled
let sortedReversedHeartRateMaxArrayAsCustomHistoricalSampple = heartRateMaxArrayAsCustomHistoricalSample.sorted { $0.date > $1.date }.reversed() as [CustomHistoricalSample]
let sortedReversedHeartRateAverageArrayAsCustomHistoricalSampple = heartRateAvgArrayAsCustomHistoricalSample.sorted { $0.date > $1.date }.reversed() as [CustomHistoricalSample]
print("handler called = \(sortedReversedHeartRateMaxArrayAsCustomHistoricalSampple.count)")
handler(sortedReversedHeartRateMaxArrayAsCustomHistoricalSampple, sortedReversedHeartRateAverageArrayAsCustomHistoricalSampple)
}
} //End getHeartRateMaxFromWorkouts
将leave置于callback的顶部是一个很好的做法
guard error == nil else { print("get heart rate error"); dispatchGroup.leave() return ; }
guard let unwrappedResults = results as? [HKQuantitySample] else { print("get heart rate error"); dispatchGroup.leave(); return}
let heartRatesAsDouble = unwrappedResults.map {$0.quantity.doubleValue(for: heartRateUnit)}
guard let max = heartRatesAsDouble.max() else { dispatchGroup.leave(); return }
let maxAsCustomHistoricalSample = CustomHistoricalSample(value: max, date: workout.startDate)
heartRateMaxArrayAsCustomHistoricalSample.append(maxAsCustomHistoricalSample)
let average = heartRatesAsDouble.average
let averageAsCustomHistoricalSample = CustomHistoricalSample(value: average, date: workout.startDate)
dispatchGroup.leave()
heartRateAvgArrayAsCustomHistoricalSample.append(averageAsCustomHistoricalSample)
当您在完成块中出错时,我认为您没有离开调度组。在每个错误情况下,只需离开组。当你无法通过防护时,你应该将组留在else块中。我不认为这是因为1没有错误打印在控制台中,2我在dispatchgroup的正上方放置了一个断点。离开并点击它,此防护让max=heartRatesAsDouble.max else{return}是的,你们都是对的,绝对不会在错误区离开,或者,正如@Sh_Khan所说,将其放在顶部是不好的,因为可能会在该块的其余部分完成之前调用notify,并且notify块可能依赖于此数据。同意将其放在所有错误块和底部是更好的做法path@rmaddy我认为这可能会损害最后的反应,但是,如果发生错误,则不会有任何区别,因为结果已经不完整。请记住,副本中的答案比这要好得多,因为它使用了“延迟”,避免了在每个卫兵发出离开通知时将其弄得一团糟。