Подтвердить что ты не робот

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

Я делаю быстрое приложение iOS, которое интегрируется с подсчетом пользовательского шага, как сообщается в приложении "Здоровье". Я могу легко найти счетчик пользовательских шагов за последний час, используя это как мой предикат:

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

Итак, как я могу получить счетчик пользовательского шага для текущего дня с таким же количеством шагов, как указано в "Здоровье", например, на рисунке: введите описание изображения здесь

4b9b3361

Ответ 1

Вот правильный путь, используя 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)
    }

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

Ответ 2

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

Swift 4.2:

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

Ответ 3

Запрос, который вы использовали, принимает все пользовательские шаги, сделанные пользователем из Healthkit, но не делает интеллектуальный фильтр из повторяющихся шагов, которые делает приложение для здоровья. Вместо этого вы хотите получить агрегированные данные шага, которые создает приложение 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)
}

Ответ 4

Используя приведенные выше ответы и от 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)
        }

Ответ 5

Для быстрой 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)")
                    }
                }
            }

Ответ 6

Если вы хотите получить общее количество шагов за каждый день за определенный период времени, используйте 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)

Ответ 7

Можно ли вернуть количество шагов в виде целого, а не двойного?