HealthKit Swift получает сегодняшние шаги

Я делаю приложение swift 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, а не начало дня, где находится пользователь), и я также получаю сильно завышенные значения шагов (по неизвестным причинам).

Итак, как я могу получить счетчик шагов пользователя за текущий день с тем же количеством шагов, что и в Health, как показано здесь:enter image description here

4 ответов


вот правильный способ использования HKStatisticsCollectionQuery любезно предоставлено направление из кода выше.

это написано в Swift 3, поэтому вам может потребоваться преобразовать часть кода обратно в 2.3 или 2, если еще не на 3.

Swift 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)
    }

С

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];

HKStatisticsCollectionQuery лучше подходит для использования, когда вы хотите получить данные за промежуток времени. Используйте HKStatisticsQuery, чтобы просто получить шаги для определенного дня.

Swift 4:

    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)
    }

запрос, который вы использовали, принимает все записанные шаги пользователя из 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)
}

используя приведенные выше ответы и от Apple здесь:https://developer.apple.com/reference/healthkit/hkstatisticsquery Я получил следующее Для работы в swift 2.3 на Xcode 8.0.

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)
        }