【问题标题】:HealthKit Swift getting today's stepsHealthKit Swift 获取今天的步骤
【发布时间】:2016-04-11 21:29:11
【问题描述】:

我正在制作一个快速的 iOS 应用程序,该应用程序与 Health 应用程序报告的用户步数相集成。我可以很容易地找到用户在过去一小时内的步数,以此作为我的谓词:

let anHourBeforeNow: NSDate = NSDate().dateByAddingTimeInterval(-60 * 60)
let predicate = HKQuery.predicateForSamplesWithStartDate(anHourBeforeNow, endDate: NSDate(), options: .None)

剩下的我已经准备好了,所以我可以成功地访问用户最后一小时的步数。 但我如何才能访问用户从一天开始以来的步数数据,例如步数部分中显示的健康应用程序?

我正在尝试做这样的事情:

let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)
let predicate = HKQuery.predicateForSamplesWithStartDate(newDate, endDate: NSDate(), options: .None)

但是这段代码没有针对时区进行调整(所以它给了我 UTC 的一天的开始,而不是用户所在的一天的开始)而且我的步数也被高度夸大了(原因未知) .

那么我怎样才能获得用户当天的步数,与健康中报告的步数相同,如下图所示:

【问题讨论】:

标签: ios swift healthkit


【解决方案1】:

HKStatisticsCollectionQuery 更适合在您想要检索一段时间内的数据时使用。使用 HKStatisticsQuery 获取特定日期的步骤。

斯威夫特 5:

let healthStore = HKHealthStore()

func getTodaysSteps(completion: @escaping (Double) -> Void) {
    let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!
    
    let now = Date()
    let startOfDay = Calendar.current.startOfDay(for: now)
    let predicate = HKQuery.predicateForSamples(
        withStart: startOfDay,
        end: now,
        options: .strictStartDate
    )
    
    let query = HKStatisticsQuery(
        quantityType: stepsQuantityType,
        quantitySamplePredicate: predicate, 
        options: .cumulativeSum
    ) { _, result, _ in
        guard let result = result, let sum = result.sumQuantity() else {
            completion(0.0)
            return
        }
        completion(sum.doubleValue(for: HKUnit.count()))
    }
    
    healthStore.execute(query)
}

【讨论】:

  • 这个方案比公认的方案更简单、更高效。
  • 当然,我发布了一个例子。
  • 我们可以分别计算跑步和步行的步数吗?
  • @PrashantTukadiya 是的,你只需要使用不同的数量类型。
【解决方案2】:

根据上述代码的指示,这是使用 HKStatisticsCollectionQuery 的正确方法。

这是用 Swift 3 编写的,因此您可能需要将一些代码转换回 2.3 或 2(如果尚未在 3 上)。

斯威夫特 3

 func retrieveStepCount(completion: (stepRetrieved: Double) -> Void) {

        //   Define the Step Quantity Type
        let stepsCount = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)

        //   Get the start of the day         
        let date = Date()
        let cal = Calendar(identifier: Calendar.Identifier.gregorian)
        let newDate = cal.startOfDay(for: date)

        //  Set the Predicates & Interval
        let predicate = HKQuery.predicateForSamples(withStart: newDate, end: Date(), options: .strictStartDate)
        var interval = DateComponents()
        interval.day = 1

        //  Perform the Query
        let query = HKStatisticsCollectionQuery(quantityType: stepsCount!, quantitySamplePredicate: predicate, options: [.cumulativeSum], anchorDate: newDate as Date, intervalComponents:interval)

        query.initialResultsHandler = { query, results, error in

            if error != nil {

                //  Something went Wrong
                return
            }

            if let myResults = results{
                myResults.enumerateStatistics(from: self.yesterday, to: self.today) {
                    statistics, stop in

                    if let quantity = statistics.sumQuantity() {

                        let steps = quantity.doubleValue(for: HKUnit.count())

                        print("Steps = \(steps)")
                        completion(stepRetrieved: steps)

                    }
                }
            }


        }

        storage.execute(query)
    }

Objective-C

HKQuantityType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];

NSDate *today = [NSDate date];
NSDate *startOfDay = [[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian] startOfDayForDate:today];

NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startOfDay endDate:today options:HKQueryOptionStrictStartDate];
NSDateComponents *interval = [[NSDateComponents alloc] init];
interval.day = 1;

HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:type quantitySamplePredicate:predicate options:HKStatisticsOptionCumulativeSum anchorDate:startOfDay intervalComponents:interval];

query.initialResultsHandler = ^(HKStatisticsCollectionQuery * _Nonnull query, HKStatisticsCollection * _Nullable result, NSError * _Nullable error) {
  if (error != nil) {
    // TODO
  } else {
    [result enumerateStatisticsFromDate:startOfDay toDate:today withBlock:^(HKStatistics * _Nonnull result, BOOL * _Nonnull stop) {
      HKQuantity *quantity = [result sumQuantity];
      double steps = [quantity doubleValueForUnit:[HKUnit countUnit]];
      NSLog(@"Steps : %f", steps);
    }];
  }
};

[self.storage executeQuery:query];

【讨论】:

  • @Gugulethu 你能指导我如何截断手动添加的步骤吗?
  • @Byte 只是想了解您的问题 - 您想截断从 HealthKit 以外的其他来源手动添加的步骤?
  • 不,我想获取 iphone 检测到的所有步骤,并由其他跟踪器自动添加。但我不希望用户手动添加到健康应用程序中的那些步骤。
  • 我还真不知道该怎么做!会做一些研究并尽快回复您。
  • self.yesterday 和 self.today 来自哪里?
【解决方案3】:

对于 swift 4.2

1) 获取 HealthKitPermission

import HealthKit

func getHealthKitPermission() {

    delay(0.1) {
        guard HKHealthStore.isHealthDataAvailable() else {
            return
        }

        let stepsCount = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!

        self.healthkitStore.requestAuthorization(toShare: [], read: [stepsCount]) { (success, error) in
            if success {
                print("Permission accept.")
            }
            else {
                if error != nil {
                    print(error ?? "")
                }
                print("Permission denied.")
            }
        }
    }
}

2) 获取特定日期的步数

func getStepsCount(forSpecificDate:Date, completion: @escaping (Double) -> Void) {
        let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!
        let (start, end) = self.getWholeDate(date: forSpecificDate)

        let predicate = HKQuery.predicateForSamples(withStart: start, end: end, options: .strictStartDate)

        let query = HKStatisticsQuery(quantityType: stepsQuantityType, quantitySamplePredicate: predicate, options: .cumulativeSum) { _, result, _ in
            guard let result = result, let sum = result.sumQuantity() else {
                completion(0.0)
                return
            }
            completion(sum.doubleValue(for: HKUnit.count()))
        }

        self.healthKitStore.execute(query)
    }

    func getWholeDate(date : Date) -> (startDate:Date, endDate: Date) {
        var startDate = date
        var length = TimeInterval()
        _ = Calendar.current.dateInterval(of: .day, start: &startDate, interval: &length, for: startDate)
        let endDate:Date = startDate.addingTimeInterval(length)
        return (startDate,endDate)
    }

如何使用

self.getStepsCount(forSpecificDate: Date()) { (steps) in
                if steps == 0.0 {
                    print("steps :: \(steps)")
                }
                else {
                    DispatchQueue.main.async {
                        print("steps :: \(steps)")
                    }
                }
            }

【讨论】:

    【解决方案4】:

    如果您想获取一段时间内每天的总步数,请使用HKStatisticsCollectionQuery,Swift 4.2 中的代码

    let startDate = Date().addingTimeInterval(-3600 * 24 * 7)
    let endDate = Date()
    
    let predicate = HKQuery.predicateForSamples(
      withStart: startDate,
      end: endDate,
      options: [.strictStartDate, .strictEndDate]
    )
    
    // interval is 1 day
    var interval = DateComponents()
    interval.day = 1
    
    // start from midnight
    let calendar = Calendar.current
    let anchorDate = calendar.date(bySettingHour: 12, minute: 0, second: 0, of: Date())
    
    let query = HKStatisticsCollectionQuery(
      quantityType: HKSampleType.quantityType(forIdentifier: .stepCount)!,
      quantitySamplePredicate: predicate,
      options: .cumulativeSum,
      anchorDate: anchorDate!,
      intervalComponents: interval
    )
    
    query.initialResultsHandler = { query, results, error in
      guard let results = results else {
        return
      }
    
      results.enumerateStatistics(
        from: startDate,
        to: endDate,
        with: { (result, stop) in
          let totalStepForADay = result.sumQuantity()?.doubleValue(for: HKUnit.count()) ?? 0
        }
      )
    }
    
    store.execute(query)
    

    【讨论】:

      【解决方案5】:

      您使用的查询从 Healthkit 获取用户记录的所有步骤,而不是对 Health 应用执行的重复步骤进行智能过滤。相反,您希望获取 Health 应用程序在组合不同来源的步数后生成的聚合步数数据,以获得准确的计数。

      为此,您可以使用以下代码:

      func recentSteps2(completion: (Double, NSError?) -> () )
      { // this function gives you all of the steps the user has taken since the beginning of the current day.
      
          checkAuthorization() // checkAuthorization just makes sure user is allowing us to access their health data.
          let type = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount) // The type of data we are requesting
      
      
          let date = NSDate()
          let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
          let newDate = cal.startOfDayForDate(date)
          let predicate = HKQuery.predicateForSamplesWithStartDate(newDate, endDate: NSDate(), options: .None) // Our search predicate which will fetch all steps taken today
      
          // The actual HealthKit Query which will fetch all of the steps and add them up for us.
          let query = HKSampleQuery(sampleType: type!, predicate: predicate, limit: 0, sortDescriptors: nil) { query, results, error in
              var steps: Double = 0
      
              if results?.count > 0
              {
                  for result in results as! [HKQuantitySample]
                  {
                      steps += result.quantity.doubleValueForUnit(HKUnit.countUnit())
                  }
              }
      
              completion(steps, error)
          }
      
          storage.executeQuery(query)
      }
      

      【讨论】:

      • 抱歉,这是不正确的。 HKSampleQuery 返回每一步记录(它不会删除重复项),并且是一种计算与谓词匹配的样本总和的低效方法。您应该使用 HKStatisticsQuery。
      【解决方案6】:

      在此处使用上述答案和来自 Apple 的答案:https://developer.apple.com/reference/healthkit/hkstatisticsquery 我得到以下在 Xcode 8.0 上的 swift 2.3 中工作。

      class func getStepCountHealth(startDate: NSDate, endDate: NSDate, completion:(Double?, NSError?)->()) {
      
                  let healthKitStore:HKHealthStore = HKHealthStore()
      
                  //   Define the sample type
                  let sampleType = HKQuantityType.quantityTypeForIdentifier(
                  HKQuantityTypeIdentifierStepCount)
      
                  //  Set the predicate
                  let predicate = HKQuery.predicateForSamplesWithStartDate(startDate,
                                                                       endDate: endDate, options: .None)
                  // build the query
                  let sampleQuery = HKStatisticsQuery(quantityType: sampleType!,
                                            quantitySamplePredicate: predicate,
                                            options: .CumulativeSum) { query, results, error in
      
                                              if results != nil {
                                                  let quantity = results?.sumQuantity()
                                                  let unit = HKUnit.countUnit()
                                                  let totalSteps = quantity?.doubleValueForUnit(unit)
                                                  completion(totalSteps, error)
      //                                            print("totalSteps for \(endDate) are \(totalSteps!)")
                                              } else {
                                                  completion(nil, error)
      //                                            print("results are nil")
                                                  return
                                              } 
                                          }
                  // execute the Query
                  healthKitStore.executeQuery(sampleQuery)
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多