如何检查 HealthKit 功能何时完成 (Swift)
How to check when HealthKit function has been completed (Swift)
好吧,标题确实说明了一切,我无法在任何地方找到适合我的答案,所以我求助于 Whosebug。我正在尝试获取用户步数并将该值分配给 UILabel。所以这里是我的一些代码(请注意,这个函数包含在另一个 class 中,因此标签是 not 在这个函数的范围内):
func readTodayHealthData() -> Int {
var stepCount: Int = 0
func getStepsHealthData() {
let stepsUnit = HKUnit.countUnit()
let sumOption = HKStatisticsOptions.CumulativeSum
let stepsHealthDataQuery = HKStatisticsQuery(quantityType: stepsHealth, quantitySamplePredicate: predicate, options: sumOption) {
query, results, error in
if let sumQuantity = results?.sumQuantity() {
dispatch_async(dispatch_get_main_queue(), {
stepCount = sumQuantity.doubleValueForUnit(stepsUnit) * 2
})
}
}
healthKitStore?.executeQuery(stepsHealthDataQuery)
}
return stepCount
}
//Set UILabel Value
//**This code is in my View Controller which is in a separate class as a result this label is NOT within the scope of this function.**
myLabel.text = String(readTodayHealthData)
然后,当我 运行 在实际设备上使用该应用程序时,我看到标签文本为零,而且我知道我今天走了一些路 :)。所以,我认为问题是当我尝试设置标签值时,函数还没有完全执行完。
我知道这一点,因为当我使用 delay 函数并等待两秒钟时,我最终得到了一个值,但如果我不等待,那么我得到的值为零。
所以主要问题是:如何检查函数何时完全执行完毕?
完成处理程序(您已经在使用)在数据可用时被调用。 readTodayHealthData()
会 return 在那之前。
您需要使用完成处理程序范围内的数据。例如,您可以这样重写您的函数:
func updateLabel() {
var stepCount: Int = 0
func getStepsHealthData() {
let stepsUnit = HKUnit.countUnit()
let sumOption = HKStatisticsOptions.CumulativeSum
let stepsHealthDataQuery = HKStatisticsQuery(quantityType: stepsHealth, quantitySamplePredicate: predicate, options: sumOption) {
query, results, error in
if let sumQuantity = results?.sumQuantity() {
dispatch_async(dispatch_get_main_queue(), {
stepCount = sumQuantity.doubleValueForUnit(stepsUnit) * 2
self.myLabel.text = "\(stepCount)"
})
}
}
healthKitStore?.executeQuery(stepsHealthDataQuery)
}
}
这将在数据 return 编辑后更新标签。
您实际上并没有尝试检查函数是否已完成执行。您传递给 HKStatisticsQuery 的那个块实际上并不是您原始函数的一部分。如果您真的想阻止 myLabel.text=
行在块被调用之前执行,您可以使用 semaphore,但这对您的实际问题来说是一个糟糕的解决方案。为什么不让您传递给 HK 的块直接更新标签?
dispatch_async(dispatch_get_main_queue(), {
stepCount = sumQuantity.doubleValueForUnit(stepsUnit) * 2
myLabel.text = "\(stepCount)"
})
问题是您使用的操作是异步的,那么您需要妥善处理,这里有两个选择:
在主线程中的函数 getStepsHealthData
中更新 completionHandler
中的 UILabel
因为您要更新 UI,例如这样:
func getStepsHealthData() {
var stepCount: Int = 0
let stepsUnit = HKUnit.countUnit()
let sumOption = HKStatisticsOptions.CumulativeSum
let stepsHealthDataQuery = HKStatisticsQuery(quantityType: stepsHealth, quantitySamplePredicate: predicate, options: sumOption) {
query, results, error in
if let sumQuantity = results?.sumQuantity() {
dispatch_async(dispatch_get_main_queue(), {
stepCount = sumQuantity.doubleValueForUnit(stepsUnit) * 2
//Set UILabel Value
myLabel.text = String(stepCount)
})
}
}
healthKitStore?.executeQuery(stepsHealthDataQuery)
}
而且您不需要return任何东西。
如果你想 return 从函数中计算步数,那么你需要稍微玩一下闭包并按以下方式修改你的函数:
func getStepsHealthData(completion: (steps: Int) -> ()) {
var stepCount: Int = 0
let stepsUnit = HKUnit.countUnit()
let sumOption = HKStatisticsOptions.CumulativeSum
let stepsHealthDataQuery = HKStatisticsQuery(quantityType: stepsHealth, quantitySamplePredicate: predicate, options: sumOption) {
query, results, error in
if let sumQuantity = results?.sumQuantity() {
stepCount = sumQuantity.doubleValueForUnit(stepsUnit) * 2
completion(stepCount)
}
}
healthKitStore?.executeQuery(stepsHealthDataQuery)
}
然后你就可以从外面这样调用它了:
self.getStepsHealthData() { (steps) -> Void in
dispatch_async(dispatch_get_main_queue(), {
//Set UILabel Value
myLabel.text = String(stepCount)
})
}
希望对你有所帮助。
好吧,标题确实说明了一切,我无法在任何地方找到适合我的答案,所以我求助于 Whosebug。我正在尝试获取用户步数并将该值分配给 UILabel。所以这里是我的一些代码(请注意,这个函数包含在另一个 class 中,因此标签是 not 在这个函数的范围内):
func readTodayHealthData() -> Int {
var stepCount: Int = 0
func getStepsHealthData() {
let stepsUnit = HKUnit.countUnit()
let sumOption = HKStatisticsOptions.CumulativeSum
let stepsHealthDataQuery = HKStatisticsQuery(quantityType: stepsHealth, quantitySamplePredicate: predicate, options: sumOption) {
query, results, error in
if let sumQuantity = results?.sumQuantity() {
dispatch_async(dispatch_get_main_queue(), {
stepCount = sumQuantity.doubleValueForUnit(stepsUnit) * 2
})
}
}
healthKitStore?.executeQuery(stepsHealthDataQuery)
}
return stepCount
}
//Set UILabel Value
//**This code is in my View Controller which is in a separate class as a result this label is NOT within the scope of this function.**
myLabel.text = String(readTodayHealthData)
然后,当我 运行 在实际设备上使用该应用程序时,我看到标签文本为零,而且我知道我今天走了一些路 :)。所以,我认为问题是当我尝试设置标签值时,函数还没有完全执行完。
我知道这一点,因为当我使用 delay 函数并等待两秒钟时,我最终得到了一个值,但如果我不等待,那么我得到的值为零。
所以主要问题是:如何检查函数何时完全执行完毕?
完成处理程序(您已经在使用)在数据可用时被调用。 readTodayHealthData()
会 return 在那之前。
您需要使用完成处理程序范围内的数据。例如,您可以这样重写您的函数:
func updateLabel() {
var stepCount: Int = 0
func getStepsHealthData() {
let stepsUnit = HKUnit.countUnit()
let sumOption = HKStatisticsOptions.CumulativeSum
let stepsHealthDataQuery = HKStatisticsQuery(quantityType: stepsHealth, quantitySamplePredicate: predicate, options: sumOption) {
query, results, error in
if let sumQuantity = results?.sumQuantity() {
dispatch_async(dispatch_get_main_queue(), {
stepCount = sumQuantity.doubleValueForUnit(stepsUnit) * 2
self.myLabel.text = "\(stepCount)"
})
}
}
healthKitStore?.executeQuery(stepsHealthDataQuery)
}
}
这将在数据 return 编辑后更新标签。
您实际上并没有尝试检查函数是否已完成执行。您传递给 HKStatisticsQuery 的那个块实际上并不是您原始函数的一部分。如果您真的想阻止 myLabel.text=
行在块被调用之前执行,您可以使用 semaphore,但这对您的实际问题来说是一个糟糕的解决方案。为什么不让您传递给 HK 的块直接更新标签?
dispatch_async(dispatch_get_main_queue(), {
stepCount = sumQuantity.doubleValueForUnit(stepsUnit) * 2
myLabel.text = "\(stepCount)"
})
问题是您使用的操作是异步的,那么您需要妥善处理,这里有两个选择:
在主线程中的函数
getStepsHealthData
中更新completionHandler
中的UILabel
因为您要更新 UI,例如这样:func getStepsHealthData() { var stepCount: Int = 0 let stepsUnit = HKUnit.countUnit() let sumOption = HKStatisticsOptions.CumulativeSum let stepsHealthDataQuery = HKStatisticsQuery(quantityType: stepsHealth, quantitySamplePredicate: predicate, options: sumOption) { query, results, error in if let sumQuantity = results?.sumQuantity() { dispatch_async(dispatch_get_main_queue(), { stepCount = sumQuantity.doubleValueForUnit(stepsUnit) * 2 //Set UILabel Value myLabel.text = String(stepCount) }) } } healthKitStore?.executeQuery(stepsHealthDataQuery) }
而且您不需要return任何东西。
如果你想 return 从函数中计算步数,那么你需要稍微玩一下闭包并按以下方式修改你的函数:
func getStepsHealthData(completion: (steps: Int) -> ()) { var stepCount: Int = 0 let stepsUnit = HKUnit.countUnit() let sumOption = HKStatisticsOptions.CumulativeSum let stepsHealthDataQuery = HKStatisticsQuery(quantityType: stepsHealth, quantitySamplePredicate: predicate, options: sumOption) { query, results, error in if let sumQuantity = results?.sumQuantity() { stepCount = sumQuantity.doubleValueForUnit(stepsUnit) * 2 completion(stepCount) } } healthKitStore?.executeQuery(stepsHealthDataQuery) }
然后你就可以从外面这样调用它了:
self.getStepsHealthData() { (steps) -> Void in dispatch_async(dispatch_get_main_queue(), { //Set UILabel Value myLabel.text = String(stepCount) }) }
希望对你有所帮助。