如何从 WatchKit 正确获取心率?
How to properly get heart rate from WatchKit?
我想简单地显示 Apple Watch 上次记录的心率。下面是我正在尝试的,但是 updateHeartRate
的完成处理程序中的 results
变量获得了数百万条记录并杀死了应用程序(几乎看起来像是损坏的数据或做错了什么):
class InterfaceController: WKInterfaceController {
@IBOutlet var heartLabel: WKInterfaceLabel!
let heartRateUnit = HKUnit.countUnit().unitDividedByUnit(HKUnit.minuteUnit())
let heartRateQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
}
override func willActivate() {
super.willActivate()
guard HKHealthStore.isHealthDataAvailable() else {
heartLabel.setText("Not available")
return
}
requestHealthKitAuthorization()
queryHeartRateSample()
}
@IBAction func workoutMenuTapped() {
}
}
private extension InterfaceController {
func requestHealthKitAuthorization() {
guard let heartRateQuantityType = heartRateQuantityType else {
displayNotAllowed()
return
}
let dataTypes = Set(arrayLiteral: heartRateQuantityType)
HKHealthStore.sharedInstance?.requestAuthorizationToShareTypes(nil, readTypes: dataTypes) {
[unowned self] success, error in
guard success else {
self.displayNotAllowed()
return
}
self.queryHeartRateSample()
}
}
func displayNotAllowed() {
heartLabel.setText("Not allowed")
}
func queryHeartRateSample() {
guard let heartRateQuery = getHeartRateQuery() else { return }
HKHealthStore.sharedInstance?.executeQuery(heartRateQuery)
}
func updateHeartRate(samples: [HKSample]?) {
guard let heartRateSamples = samples as? [HKQuantitySample] else { return }
dispatch_async(dispatch_get_main_queue()) {
guard let sample = heartRateSamples.first else { return }
let value = sample.quantity.doubleValueForUnit(self.heartRateUnit)
self.heartLabel.setText(String(UInt16(value)))
}
}
func getHeartRateQuery() -> HKQuery? {
guard let heartRateQuantityType = heartRateQuantityType else {
displayNotAllowed()
return nil
}
let heartRateQuery = HKSampleQuery(sampleType: heartRateQuantityType,
predicate: nil,
limit: 100,
sortDescriptors: nil) {
[unowned self] query, results, error in
guard let results = results as? [HKQuantitySample] else { return }
self.updateHeartRate(results)
}
return heartRateQuery
}
}
@available(iOS 8.0, *)
public extension HKHealthStore {
class var sharedInstance: HKHealthStore? {
if !HKHealthStore.isHealthDataAvailable() {
return nil
}
struct Singleton {
static let instance = HKHealthStore()
}
return Singleton.instance
}
}
它确实要求我授予权限,但仍然没有触发更新。我做错了什么吗?
我更喜欢使用HKAnchoredObjectQuery
只搜索添加到HealthKit的新数据,它避免查询所有数据,所以你可以得到最新的心率值授予权限后,请按以下方式操作:
private let healthStore = HKHealthStore()
private let heartRateType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)!
private let heartRateUnit = HKUnit(fromString: "count/min")
/**
Start to measure the heart rate.
*/
func startToMeasure() {
self.healthStore.executeQuery(self.createStreamingQuery()!)
}
/**
Create a query to receive new heart rate data from the HealthKit store.
- returns: The created query
*/
private func createStreamingQuery() -> HKQuery {
let predicate = HKQuery.predicateForSamplesWithStartDate(NSDate(), endDate: nil, options: .None)
let query = HKAnchoredObjectQuery(type: heartRateType, predicate: predicate, anchor: nil, limit: Int(HKObjectQueryNoLimit)) {
(query, samples, deletedObjects, anchor, error) -> Void in
self.formatSamples(samples)
}
query.updateHandler = { (query, samples, deletedObjects, anchor, error) -> Void in
self.formatSamples(samples)
}
return query
}
/**
Format the samples received from HealthKit.
- parameter samples: Some samples
*/
private func formatSamples(samples: [HKSample]?) {
guard let samples = samples as? [HKQuantitySample] else { return }
guard let quantity = samples.last?.quantity else { return }
let value = Int(quantity.doubleValueForUnit(heartRateUnit))
print("HeartRate: \(value)")
}
以上代码需要集成到您的class或UIViewController
中。我在上面的代码中使用了一个谓词来按日期过滤,如果不相关,您可以将其删除。
希望对你有所帮助。
我想简单地显示 Apple Watch 上次记录的心率。下面是我正在尝试的,但是 updateHeartRate
的完成处理程序中的 results
变量获得了数百万条记录并杀死了应用程序(几乎看起来像是损坏的数据或做错了什么):
class InterfaceController: WKInterfaceController {
@IBOutlet var heartLabel: WKInterfaceLabel!
let heartRateUnit = HKUnit.countUnit().unitDividedByUnit(HKUnit.minuteUnit())
let heartRateQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
}
override func willActivate() {
super.willActivate()
guard HKHealthStore.isHealthDataAvailable() else {
heartLabel.setText("Not available")
return
}
requestHealthKitAuthorization()
queryHeartRateSample()
}
@IBAction func workoutMenuTapped() {
}
}
private extension InterfaceController {
func requestHealthKitAuthorization() {
guard let heartRateQuantityType = heartRateQuantityType else {
displayNotAllowed()
return
}
let dataTypes = Set(arrayLiteral: heartRateQuantityType)
HKHealthStore.sharedInstance?.requestAuthorizationToShareTypes(nil, readTypes: dataTypes) {
[unowned self] success, error in
guard success else {
self.displayNotAllowed()
return
}
self.queryHeartRateSample()
}
}
func displayNotAllowed() {
heartLabel.setText("Not allowed")
}
func queryHeartRateSample() {
guard let heartRateQuery = getHeartRateQuery() else { return }
HKHealthStore.sharedInstance?.executeQuery(heartRateQuery)
}
func updateHeartRate(samples: [HKSample]?) {
guard let heartRateSamples = samples as? [HKQuantitySample] else { return }
dispatch_async(dispatch_get_main_queue()) {
guard let sample = heartRateSamples.first else { return }
let value = sample.quantity.doubleValueForUnit(self.heartRateUnit)
self.heartLabel.setText(String(UInt16(value)))
}
}
func getHeartRateQuery() -> HKQuery? {
guard let heartRateQuantityType = heartRateQuantityType else {
displayNotAllowed()
return nil
}
let heartRateQuery = HKSampleQuery(sampleType: heartRateQuantityType,
predicate: nil,
limit: 100,
sortDescriptors: nil) {
[unowned self] query, results, error in
guard let results = results as? [HKQuantitySample] else { return }
self.updateHeartRate(results)
}
return heartRateQuery
}
}
@available(iOS 8.0, *)
public extension HKHealthStore {
class var sharedInstance: HKHealthStore? {
if !HKHealthStore.isHealthDataAvailable() {
return nil
}
struct Singleton {
static let instance = HKHealthStore()
}
return Singleton.instance
}
}
它确实要求我授予权限,但仍然没有触发更新。我做错了什么吗?
我更喜欢使用HKAnchoredObjectQuery
只搜索添加到HealthKit的新数据,它避免查询所有数据,所以你可以得到最新的心率值授予权限后,请按以下方式操作:
private let healthStore = HKHealthStore()
private let heartRateType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)!
private let heartRateUnit = HKUnit(fromString: "count/min")
/**
Start to measure the heart rate.
*/
func startToMeasure() {
self.healthStore.executeQuery(self.createStreamingQuery()!)
}
/**
Create a query to receive new heart rate data from the HealthKit store.
- returns: The created query
*/
private func createStreamingQuery() -> HKQuery {
let predicate = HKQuery.predicateForSamplesWithStartDate(NSDate(), endDate: nil, options: .None)
let query = HKAnchoredObjectQuery(type: heartRateType, predicate: predicate, anchor: nil, limit: Int(HKObjectQueryNoLimit)) {
(query, samples, deletedObjects, anchor, error) -> Void in
self.formatSamples(samples)
}
query.updateHandler = { (query, samples, deletedObjects, anchor, error) -> Void in
self.formatSamples(samples)
}
return query
}
/**
Format the samples received from HealthKit.
- parameter samples: Some samples
*/
private func formatSamples(samples: [HKSample]?) {
guard let samples = samples as? [HKQuantitySample] else { return }
guard let quantity = samples.last?.quantity else { return }
let value = Int(quantity.doubleValueForUnit(heartRateUnit))
print("HeartRate: \(value)")
}
以上代码需要集成到您的class或UIViewController
中。我在上面的代码中使用了一个谓词来按日期过滤,如果不相关,您可以将其删除。
希望对你有所帮助。