gpt4 book ai didi

How to make sure this code runs in the correct order?(如何确保该代码以正确的顺序运行?)

转载 作者:bug小助手 更新时间:2023-10-24 21:10:00 25 4
gpt4 key购买 nike



I have this code to get data from the health store. I am looping through information for each of the different sample types that I want to get from the health store in the fetchSampleData function. I am expecting the function to loop through and get all of the different kinds of samples and then use the completion to send that data back to the getData function. I then want to use that data in my code.

我有这个代码来从健康商店获取数据。我循环遍历希望从fetchSampleData函数中的健康存储中获取的每个不同样本类型的信息。我希望该函数遍历并获取所有不同类型的样本,然后使用完成将数据发送回getData函数。然后,我想在我的代码中使用该数据。


func getData() {
// Data types and units for health kit queries
let sampleInfo = [
("heartRate", HKObjectType.quantityType(
forIdentifier: .heartRate), "count/min"),
("heartRateVariabilitySDNN", HKObjectType.quantityType(
forIdentifier: .heartRateVariabilitySDNN), "s"),
("stepCount", HKObjectType.quantityType(
forIdentifier: .stepCount), "count"),
]

self.fetchSampleData(
sampleInfo: sampleInfo
) { samplesDict in

let sampleCount = samplesDict.count

print("Sample count: \(sampleCount)")
print(samplesDict)

if (sampleCount > 0) {
// code to do stuff with samplesDict ...
}

}
}

public func fetchSampleData(
sampleInfo: [(String, HKQuantityType?, String)],
completion: @escaping ( _ samples:
Dictionary<String, Dictionary<Date, Double>>) -> Void
) {

let numberOfDataTypes = sampleInfo.count
var resultsDict: [String: [Date: Double]] = [:]

for i in 0..<numberOfDataTypes {
let dataTypeName = sampleInfo[i].0
let sampleType = sampleInfo[i].1!
let unitString = sampleInfo[i].2
var dataTypeDictionary = [Date:Double]()

// Predicate for specifying start and end dates for the query
let predicate = HKQuery
.predicateForSamples(
withStart: Date.distantPast,
end: Date.now,
options: .strictEndDate)

// Set sorting by date.
let sortDescriptor = NSSortDescriptor(
key: HKSampleSortIdentifierStartDate,
ascending: false)

// Create the query
let query = HKSampleQuery(
sampleType: sampleType,
predicate: predicate,
limit: Int(HKObjectQueryNoLimit),
sortDescriptors: [sortDescriptor]) { (_, results, error) in

guard error == nil else {
print("Error: \(error!.localizedDescription)")
return
}

print("~~- \(results?.count) \(dataTypeName) samples returned")
for sample in results ?? [] {
let data = sample as! HKQuantitySample
let unit = HKUnit(from: unitString)
let sampleVal = data.quantity.doubleValue(for: unit)
let dateStart = data.startDate

dataTypeDictionary[dateStart] = sampleVal
}

resultsDict[dataTypeName] = dataTypeDictionary
}

healthStore.execute(query)
}

completion(resultsDict)
}

But when I run this code I am getting this for an output:

但是当我运行这段代码时,我得到的输出如下:



Sample count: 0




[:]




~~- Optional(103) heartRateVariabilitySDNN samples returned




~~- Optional(846) stepCount samples returned




~~- Optional(3127) activeEnergyBurned samples returned




~~- Optional(4470) heartRate samples returned




~~- Optional(2913) basalEnergyBurned samples returned



So the code that i was assuming would run after the fetchSampleData function was done seems to be running before the data is even returned. Is there a way that I could tell the program to only run the code involving the returned samplesDict data if the fetchSampleData has finished getting that data?

因此,我假设在fetchSampleData函数完成后运行的代码似乎在数据返回之前就已经运行了。有没有一种方法可以告诉程序只运行涉及返回的samplesDict数据的代码,如果fetchSampleData已经完成了该数据的获取?


更多回答

You need to invoke completion(resultsDict) inside the query results closure - ie. after the line resultsDict[dataTypeName] = dataTypeDictionary

您需要在查询结果闭包中调用完成(ResultsDict)-即。在行ResultsDict[dataTypeName]=dataTypeDictionary之后

The OP is trying to wait until a whole series of async tasks have completed. The solution is a little more complicated than "invoke completion inside the query results closure". I reopened the question and added an answer using a GCD DispatchGroup

操作员正在尝试等待,直到完成一系列的异步任务。该解决方案比“在查询结果闭包内调用完成”稍微复杂一些。我重新打开问题并使用GCD DispatchGroup添加了答案

This isn't a bad question, but it may have been downvoted for the unnecessarily needy title. If you ask questions in the form "how to" or "how can I" then they will sound much more confident, and you may receive less negative feedback.

这不是一个糟糕的问题,但它可能被否决了,因为这个不必要的标题。如果你以“怎么做”或“我怎么做”的形式问问题,他们听起来会更自信,你可能会得到更少的负面反馈。

优秀答案推荐

Your fetchSampleData function loops through numberOfDataTypes, firing off an async query to the health store each time through the loop. Then, before any of those async calls can complete, you call your function's completion handler. If you want to wait until all the queries complete you should set up a GCD DispatchGroup to synchronize all of those calls.

您的fetchSampleData函数循环通过number OfDataTypes,每次通过循环都会触发对健康存储的异步查询。然后,在这些异步调用中的任何一个完成之前,调用函数的完成处理程序。如果要等到所有查询完成,则应设置GCD DispatchGroup以同步所有这些呼叫。


I just created a question and answer explaining DispatchGroups and providing a simple example using them.

我刚刚创建了一个问题和答案,解释了DispatchGroups并提供了一个使用它们的简单示例。


Appling that approach to your code might look like the below (see all the MARK: New code marks in the code for the changes.)

将该方法应用于您的代码可能如下所示(请参见代码中的所有Mark:new代码标记以进行更改)。


    public func fetchSampleData(
sampleInfo: [(String, HKQuantityType?, String)],
completion: @escaping ( _ samples:
Dictionary<String, Dictionary<Date, Double>>) -> Void
) {

let numberOfDataTypes = sampleInfo.count
var resultsDict: [String: [Date: Double]] = [:]

// -------------------------------
// MARK: New code
let dispatchGroup = DispatchGroup()

// Create a DispatchWorkItem to call our completion handler once all our tasks have finished.
let workItem = DispatchWorkItem() {
completion(resultsDict)
}
// -------------------------------

for i in 0..<numberOfDataTypes {
let dataTypeName = sampleInfo[i].0
let sampleType = sampleInfo[i].1!
let unitString = sampleInfo[i].2
var dataTypeDictionary = [Date:Double]()

// Predicate for specifying start and end dates for the query
let predicate = HKQuery
.predicateForSamples(
withStart: Date.distantPast,
end: Date.now,
options: .strictEndDate)

// Set sorting by date.
let sortDescriptor = NSSortDescriptor(
key: HKSampleSortIdentifierStartDate,
ascending: false)

// Create the query
// MARK: New code
dispatchGroup.enter() // Tell the dispatch group we have added another async task
let query = HKSampleQuery(
sampleType: sampleType,
predicate: predicate,
limit: Int(HKObjectQueryNoLimit),
sortDescriptors: [sortDescriptor]) { (_, results, error) in

guard error == nil else {
print("Error: \(error!.localizedDescription)")
return
}

print("~~- \(results?.count) \(dataTypeName) samples returned")
for sample in results ?? [] {
let data = sample as! HKQuantitySample
let unit = HKUnit(from: unitString)
let sampleVal = data.quantity.doubleValue(for: unit)
let dateStart = data.startDate

dataTypeDictionary[dateStart] = sampleVal
}

resultsDict[dataTypeName] = dataTypeDictionary
// MARK: New code
dispatchGroup.leave() // tell the dispatch group this task has been completed

}

healthStore.execute(query)
}
dispatchGroup.notify(queue: DispatchQueue.main, work: workItem) // MARK: New code
}
}

更多回答

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