如何 return HKStatisticsQuery 的结果到 Swift 2 中的变量?
How to return result of HKStatisticsQuery to a variable in Swift 2?
底部更新于 2016 年 1 月 30 日@7:40PM EST
所以我正在尝试 运行 一个 StatisticsQuery 来获取存储在 HealthKit 中的一天的总数 DistanceRunningWalking
,然后将该查询的结果存储在一个变量中,以供以后使用.查询似乎工作正常,因为我已经测试过将查询结果 (totalDistance
) 从函数内打印到标签。我遇到的问题 运行 是在尝试将结果保存到变量时。
这是我的 HealthKitManager.swift 文件中的代码:
import HealthKit
class HealthKitManager {
class var sharedInstance: HealthKitManager {
struct Singleton {
static let instance = HealthKitManager()
}
return Singleton.instance
}
let healthStore: HKHealthStore? = {
if HKHealthStore.isHealthDataAvailable() {
return HKHealthStore()
} else {
return nil
}
}()
let distanceCount = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning)
let distanceUnit = HKUnit(fromString: "mi")
}
ViewController 顶部的代码:(这是我要保存到的变量)
let healthKitManager = HealthKitManager.sharedInstance
//Set up variable to contain result of query
var distanceTotalLength:Double?
viewDidLoad
中的代码:
//Run the function
requestHealthKitAuthorization()
//Set value of variable to query result
distanceTotalLength = queryDistanceSum()
ViewController正文中的代码:
func requestHealthKitAuthorization() {
let dataTypesToRead = NSSet(objects: healthKitManager.distanceCount!)
healthKitManager.healthStore?.requestAuthorizationToShareTypes(nil, readTypes: dataTypesToRead as NSSet as? Set<HKObjectType>, completion: { [unowned self] (success, error) in
if success {
self.queryDistanceSum()
} else {
print(error!.description)
}
})
}
func queryDistanceSum() {
let sumOption = HKStatisticsOptions.CumulativeSum
let startDate = NSDate().dateByRemovingTime()
let endDate = NSDate()
let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: endDate, options: [])
let statisticsSumQuery = HKStatisticsQuery(quantityType: healthKitManager.distanceCount!, quantitySamplePredicate: predicate, options: sumOption) {
[unowned self] (query, result, error) in
if let sumQuantity = result?.sumQuantity() {
dispatch_async(dispatch_get_main_queue(), {
let totalDistance = sumQuantity.doubleValueForUnit(self.healthKitManager.distanceUnit)
self.distanceTotalLength = totalDistance
})
}
}
healthKitManager.healthStore?.executeQuery(statisticsSumQuery)
}
在最后一行 return (distanceTotalLength)!
我在启动显示为 fatal error: unexpectedly found nil while unwrapping an Optional value
的应用程序时遇到错误。我已经意识到这很可能是处理范围的问题(尽管我可能做错了其他事情,所以请指出任何问题)但我未能 see/find 我自己解决问题的方法。
如有任何帮助,我们将不胜感激,在此先致谢!
更新:01/30/16 @~7:40PM EST
好的,所以我一直在尝试自己解决这个问题,并且发现了一个发现:代码确实有效。通过将 0
的初始值分配给 ViewController 顶部的 distanceTotalLength
,我能够 运行 应用程序而不会出现致命错误。但是,当我随后尝试通过 prepareForSegue 函数将 distanceTotalLength
的值传递给另一个视图时,我意识到它毕竟被分配了。当我转到那个视图时,它没有使用 0
的初始值,而是查询的结果。
我测试这个的方法是设置变量:var distanceTotalLength:Double = 0
在我的 viewController 的最顶部,在 viewDidLoad
之前 然后在 viewDidLoad
我分配使用 distanceLabel.text = String(distanceTotalLength)
的标签值,正如我所说,标签最终显示为 0
。但是当我转换到另一个视图时,传递 distanceTotalLength
的值并打印出那里的值,它起作用了。在第二个屏幕上,它打印查询结果,而不是 0
.
所以我假设问题是查询 运行s 然后在视图已经加载所有预定义值之后分配值。不幸的是,这是我再次陷入困境的地方。既然我已经走到这一步,有人知道如何帮助我吗?
你是对的。在 HKStatisticsQuery
完成执行后调用的 completionHandler 闭包发生在稍后的破坏时间。将查询执行想象成在邮件中向某人发送一封信,然后等待他们的回复;这不会是立竿见影的,但在此期间您可以离开并做其他事情。
要在您的代码中处理此问题,请将您自己的完成闭包添加到 queryDistanceSum 方法。然后在设置 self.distanceTotalLength = totalDistance
之后,调用那个闭包。在实现闭包代码时,在设置距离后添加任何需要做的事情,比如更新你的 UI.
func queryDistanceSum(completion: () -> Void) { // <----- add the closure here
let sumOption = HKStatisticsOptions.CumulativeSum
let startDate = NSDate().dateByRemovingTime()
let endDate = NSDate()
let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: endDate, options: [])
let statisticsSumQuery = HKStatisticsQuery(quantityType: healthKitManager.distanceCount!, quantitySamplePredicate: predicate, options: sumOption) {
[unowned self] (query, result, error) in
if let sumQuantity = result?.sumQuantity() {
dispatch_async(dispatch_get_main_queue(), {
let totalDistance = sumQuantity.doubleValueForUnit(self.healthKitManager.distanceUnit)
self.distanceTotalLength = totalDistance
completion() // <----- call the closure here
})
}
}
healthKitManager.healthStore?.executeQuery(statisticsSumQuery)
}
// Then whenever you need to update the distance sum call the function
// with the closure, then handle the result as needed
queryDistanceSum { () -> () in
// distanceTotalLength has now been set.
// Update UI for new distance value or whatever you need to do
}
无论何时实现闭包,您都必须假设闭包中的代码将在稍后执行。
底部更新于 2016 年 1 月 30 日@7:40PM EST
所以我正在尝试 运行 一个 StatisticsQuery 来获取存储在 HealthKit 中的一天的总数 DistanceRunningWalking
,然后将该查询的结果存储在一个变量中,以供以后使用.查询似乎工作正常,因为我已经测试过将查询结果 (totalDistance
) 从函数内打印到标签。我遇到的问题 运行 是在尝试将结果保存到变量时。
这是我的 HealthKitManager.swift 文件中的代码:
import HealthKit
class HealthKitManager {
class var sharedInstance: HealthKitManager {
struct Singleton {
static let instance = HealthKitManager()
}
return Singleton.instance
}
let healthStore: HKHealthStore? = {
if HKHealthStore.isHealthDataAvailable() {
return HKHealthStore()
} else {
return nil
}
}()
let distanceCount = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning)
let distanceUnit = HKUnit(fromString: "mi")
}
ViewController 顶部的代码:(这是我要保存到的变量)
let healthKitManager = HealthKitManager.sharedInstance
//Set up variable to contain result of query
var distanceTotalLength:Double?
viewDidLoad
中的代码:
//Run the function
requestHealthKitAuthorization()
//Set value of variable to query result
distanceTotalLength = queryDistanceSum()
ViewController正文中的代码:
func requestHealthKitAuthorization() {
let dataTypesToRead = NSSet(objects: healthKitManager.distanceCount!)
healthKitManager.healthStore?.requestAuthorizationToShareTypes(nil, readTypes: dataTypesToRead as NSSet as? Set<HKObjectType>, completion: { [unowned self] (success, error) in
if success {
self.queryDistanceSum()
} else {
print(error!.description)
}
})
}
func queryDistanceSum() {
let sumOption = HKStatisticsOptions.CumulativeSum
let startDate = NSDate().dateByRemovingTime()
let endDate = NSDate()
let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: endDate, options: [])
let statisticsSumQuery = HKStatisticsQuery(quantityType: healthKitManager.distanceCount!, quantitySamplePredicate: predicate, options: sumOption) {
[unowned self] (query, result, error) in
if let sumQuantity = result?.sumQuantity() {
dispatch_async(dispatch_get_main_queue(), {
let totalDistance = sumQuantity.doubleValueForUnit(self.healthKitManager.distanceUnit)
self.distanceTotalLength = totalDistance
})
}
}
healthKitManager.healthStore?.executeQuery(statisticsSumQuery)
}
在最后一行 return (distanceTotalLength)!
我在启动显示为 fatal error: unexpectedly found nil while unwrapping an Optional value
的应用程序时遇到错误。我已经意识到这很可能是处理范围的问题(尽管我可能做错了其他事情,所以请指出任何问题)但我未能 see/find 我自己解决问题的方法。
如有任何帮助,我们将不胜感激,在此先致谢!
更新:01/30/16 @~7:40PM EST
好的,所以我一直在尝试自己解决这个问题,并且发现了一个发现:代码确实有效。通过将 0
的初始值分配给 ViewController 顶部的 distanceTotalLength
,我能够 运行 应用程序而不会出现致命错误。但是,当我随后尝试通过 prepareForSegue 函数将 distanceTotalLength
的值传递给另一个视图时,我意识到它毕竟被分配了。当我转到那个视图时,它没有使用 0
的初始值,而是查询的结果。
我测试这个的方法是设置变量:var distanceTotalLength:Double = 0
在我的 viewController 的最顶部,在 viewDidLoad
之前 然后在 viewDidLoad
我分配使用 distanceLabel.text = String(distanceTotalLength)
的标签值,正如我所说,标签最终显示为 0
。但是当我转换到另一个视图时,传递 distanceTotalLength
的值并打印出那里的值,它起作用了。在第二个屏幕上,它打印查询结果,而不是 0
.
所以我假设问题是查询 运行s 然后在视图已经加载所有预定义值之后分配值。不幸的是,这是我再次陷入困境的地方。既然我已经走到这一步,有人知道如何帮助我吗?
你是对的。在 HKStatisticsQuery
完成执行后调用的 completionHandler 闭包发生在稍后的破坏时间。将查询执行想象成在邮件中向某人发送一封信,然后等待他们的回复;这不会是立竿见影的,但在此期间您可以离开并做其他事情。
要在您的代码中处理此问题,请将您自己的完成闭包添加到 queryDistanceSum 方法。然后在设置 self.distanceTotalLength = totalDistance
之后,调用那个闭包。在实现闭包代码时,在设置距离后添加任何需要做的事情,比如更新你的 UI.
func queryDistanceSum(completion: () -> Void) { // <----- add the closure here
let sumOption = HKStatisticsOptions.CumulativeSum
let startDate = NSDate().dateByRemovingTime()
let endDate = NSDate()
let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: endDate, options: [])
let statisticsSumQuery = HKStatisticsQuery(quantityType: healthKitManager.distanceCount!, quantitySamplePredicate: predicate, options: sumOption) {
[unowned self] (query, result, error) in
if let sumQuantity = result?.sumQuantity() {
dispatch_async(dispatch_get_main_queue(), {
let totalDistance = sumQuantity.doubleValueForUnit(self.healthKitManager.distanceUnit)
self.distanceTotalLength = totalDistance
completion() // <----- call the closure here
})
}
}
healthKitManager.healthStore?.executeQuery(statisticsSumQuery)
}
// Then whenever you need to update the distance sum call the function
// with the closure, then handle the result as needed
queryDistanceSum { () -> () in
// distanceTotalLength has now been set.
// Update UI for new distance value or whatever you need to do
}
无论何时实现闭包,您都必须假设闭包中的代码将在稍后执行。