如何检索一组 HealthKit 记录及其元数据

Posted

技术标签:

【中文标题】如何检索一组 HealthKit 记录及其元数据【英文标题】:How to retrieve an array of HealthKit records and their metadata 【发布时间】:2015-05-27 12:26:26 【问题描述】:

我正在学习一些关于使用 swift 的 HealthKit 教程,我正在学习的教程之一是如何从 HealthKit 中检索一些数据,例如体重、身高年龄。本教程展示了如何检索每个它们的最新记录,以下代码显示:

func readMostRecentSample(sampleType:HKSampleType , completion: ((HKSample!, NSError!) -> Void)!)


// 1. Build the Predicate
let past = NSDate.distantPast() as! NSDate
let now   = NSDate()
let mostRecentPredicate = HKQuery.predicateForSamplesWithStartDate(past, endDate:now, options: .None)

// 2. Build the sort descriptor to return the samples in descending order
let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate, ascending: false)
// 3. we want to limit the number of samples returned by the query to just 1 (the most recent)
let limit = 1

// 4. Build samples query
let sampleQuery = HKSampleQuery(sampleType: sampleType, predicate: mostRecentPredicate, limit: limit, sortDescriptors: [sortDescriptor])
   (sampleQuery, results, error ) -> Void in

    if let queryError = error 
      completion(nil,error)
      return;
    

    // Get the first sample
    let mostRecentSample = results.first as? HKQuantitySample

    // Execute the completion closure
    if completion != nil 
      completion(mostRecentSample,nil)
    

// 5. Execute the Query
self.healthKitStore.executeQuery(sampleQuery)

然后开发者在其他类中传递参数来获取所需的最近记录,下面的代码展示了获取高度记录的方法:

func updateHeight()

// 1. Construct an HKSampleType for Height
let sampleType = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeight)

// 2. Call the method to read the most recent Height sample
self.healthManager?.readMostRecentSample(sampleType, completion:  (mostRecentHeight, error) -> Void in

  if( error != nil )
  
    println("Error reading height from HealthKit Store: \(error.localizedDescription)")
    return;
  

  var heightLocalizedString = self.kUnknownString;
  self.height = mostRecentHeight as? HKQuantitySample;
  // 3. Format the height to display it on the screen
  if let meters = self.height?.quantity.doubleValueForUnit(HKUnit.meterUnit()) 
    let heightFormatter = NSLengthFormatter()
    heightFormatter.forPersonHeightUse = true;
    heightLocalizedString = heightFormatter.stringFromMeters(meters);
  


  // 4. Update UI. HealthKit use an internal queue. We make sure that we interact with the UI in the main thread
  dispatch_async(dispatch_get_main_queue(),  () -> Void in
    self.heightLabel.text = heightLocalizedString
    self.updateBMI()
  );
)


我创建了一个与第一个方法类似的方法,但只进行了一些更改,因此我可以获得一个包含 10 条葡萄糖记录的数组:

func readAllGlucose(sampleType:HKSampleType , completion: (([HKSample!], NSError!) -> Void)!)


    let now   = NSDate()
    let df = NSDateFormatter()
    df.dateFormat = "yyyy-MM-dd"
    let pastt = df.dateFromString("2015-05-18")

    //let mostRecentPredicate = HKQuery.predicateForSamplesWithStartDate(past, endDate:now, options: .None)
    let allreadings = HKQuery.predicateForSamplesWithStartDate(pastt, endDate: now, options: .None)

    // 2. Build the sort descriptor to return the samples in descending order
    let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate, ascending: false)
    // 3. we want to limit the number of samples returned by the query to just 1 (the most recent)
    let limit = 10

    // 4. Build samples query

    let sampleQuery = HKSampleQuery(sampleType: sampleType, predicate: allreadings, limit: limit, sortDescriptors: [sortDescriptor])
         (sampleQuery, results, error ) -> Void in

            if let queryError = error 
                completion([nil],error)
                return;
            

            // Get the first sample
            let allSamples = results as? [HKQuantitySample]

            // Execute the completion closure
            if completion != nil 
                completion(allSamples!,nil)
            
    
    // 5. Execute the Query
    self.healthKitStore.executeQuery(sampleQuery)

然后我创建了另一个类似于 updateHeight() 方法的方法,但当然需要进行必要的更改:

func updateLastGlucoRecords()

    // 1. Construct an HKSampleType for weight
    let sampleType = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBloodGlucose)

    // 2. Call the method to read the most recent weight sample
    self.healthManager?.readAllGlucose(sampleType, completion: ([allReadings], error) -> Void in

        if (error != nil) 
            println("Error reading glucose readings from HealthKit Store: \(error.localizedDescription)")
            return;
        

        var glucoseLocalizedString = self.kUnknownString;
        self.glucose = allReadings as? [HKQuantitySample]
        for reading in readings 

            if let record = reading.quantity 
                glucoseLocalizedString = record
            
            dispatch_async(dispatch_get_main_queue(),  () -> Void in
                self.glucoReadings.append("\(glucoseLocalizedString)")
            )

        


    )
    self.healthManager?.readMostRecentSample(sampleType, completion:  (mostRecentWeight, error) -> Void in

        if( error != nil )
        
            println("Error reading weight from HealthKit Store: \(error.localizedDescription)")
            return;
        

        var weightLocalizedString = self.kUnknownString;
        // 3. Format the weight to display it on the screen
        self.weight = mostRecentWeight as? HKQuantitySample;
        if let kilograms = self.weight?.quantity.doubleValueForUnit(HKUnit.gramUnitWithMetricPrefix(.Kilo)) 
            let weightFormatter = NSMassFormatter()
            weightFormatter.forPersonMassUse = true;
            weightLocalizedString = weightFormatter.stringFromKilograms(kilograms)
        

        // 4. Update UI in the main thread
        dispatch_async(dispatch_get_main_queue(),  () -> Void in
            self.weightLabel.text = weightLocalizedString
            self.updateBMI()

        );
    );

但不幸的是,我遇到了两个错误:

self.healthManager?.readAllGlucose(sampleType, completion: ([allReadings], error) -> Void in

第一个错误:

[HKSample!]' 不是 '

的子类型

第二个错误:

使用未声明的类型“allReadings”

我还有一个问题,如何从每个对象中获取元数据,我想获取插入数据的日期和时间

如果有人有任何想法可以解决这个问题,我将不胜感激

提前致谢

【问题讨论】:

Get an array of Blood Glucose records from HealthKit 的可能重复项 【参考方案1】:

我遇到了同样的问题。请在下面查看我的代码。 1.) allReadings 错误是由于您没有传递 HKSample 的数组,所以要做到这一点,所以您必须写成:let allReadings:[HKSample!] 然后传递 allReadings。

func readAllSample(sampleType:HKSampleType , completion: (([HKSample!], NSError!) -> Void)!)

    let now   = NSDate()
    let past = now.dateByAddingTimeInterval(-10*24*60*60) as NSDate!
    let mostRecentPredicate = HKQuery.predicateForSamplesWithStartDate(past, endDate:now, options: .None)
    let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate, ascending: false)
    let limit = 10
    let sampleQuery = HKSampleQuery(sampleType: sampleType, predicate: mostRecentPredicate, limit: limit, sortDescriptors: [sortDescriptor])
         (sampleQuery, results, error ) -> Void in

            if(error == nil)
            
                print(results)
            

    
    self.healthKitStore.executeQuery(sampleQuery)

【讨论】:

以上是关于如何检索一组 HealthKit 记录及其元数据的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 HealthKit 从 iHealth 获取元数据?

如何使用 HealthKit 从 iHealth 获取元数据?

如何使用 Swift 在 healthkit 中访问锻炼的元数据

从 HealthKit 获取一系列血糖记录

使用swift在iOS上本地保存和检索包含所有元数据的照片

如何检索 PHAsset 的元数据?