Ottieni il conteggio totale dei passaggi per ogni data in HealthKit

Qual è il modo migliore per ottenere un conteggio totale dei passaggi per ogni giorno registrato in HealthKit . Con il metodo di HKSampleQuery initWithSampleType (vedi sotto) posso impostare una data di inizio e di fine per la query usando NSPredicate , ma il metodo restituisce un array con molti HKQuantitySamples al giorno.

 - (instancetype)initWithSampleType:(HKSampleType *)sampleType predicate:(NSPredicate *)predicate limit:(NSUInteger)limit sortDescriptors:(NSArray *)sortDescriptors resultsHandler:(void (^)(HKSampleQuery *query, NSArray *results, NSError *error))resultsHandler 

Immagino di poter interrogare tutti i conteggi dei passi registrati e passare attraverso l’array e calcolare il conteggio degli step totali per ogni giorno, ma spero in una soluzione più semplice dato che ci saranno migliaia di oggetti HKSampleQuery. C’è un modo per avere initWithSampleType restituire un numero totale di passi al giorno?

È necessario utilizzare HKStatisticsCollectionQuery :

 NSCalendar *calendar = [NSCalendar currentCalendar]; NSDateComponents *interval = [[NSDateComponents alloc] init]; interval.day = 1; NSDateComponents *anchorComponents = [calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]]; anchorComponents.hour = 0; NSDate *anchorDate = [calendar dateFromComponents:anchorComponents]; HKQuantityType *quantityType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; // Create the query HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType quantitySamplePredicate:nil options:HKStatisticsOptionCumulativeSum anchorDate:anchorDate intervalComponents:interval]; // Set the results handler query.initialResultsHandler = ^(HKStatisticsCollectionQuery *query, HKStatisticsCollection *results, NSError *error) { if (error) { // Perform proper error handling here NSLog(@"*** An error occurred while calculating the statistics: %@ ***",error.localizedDescription); } NSDate *endDate = [NSDate date]; NSDate *startDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:-7 toDate:endDate options:0]; // Plot the daily step counts over the past 7 days [results enumerateStatisticsFromDate:startDate toDate:endDate withBlock:^(HKStatistics *result, BOOL *stop) { HKQuantity *quantity = result.sumQuantity; if (quantity) { NSDate *date = result.startDate; double value = [quantity doubleValueForUnit:[HKUnit countUnit]]; NSLog(@"%@: %f", date, value); } }]; }; [self.healthStore executeQuery:query]; 

Porta a Swift senza dipendenza dalla libreria SwiftDate

  let calendar = NSCalendar.current let interval = NSDateComponents() interval.day = 1 var anchorComponents = calendar.dateComponents([.day, .month, .year], from: NSDate() as Date) anchorComponents.hour = 0 let anchorDate = calendar.date(from: anchorComponents) // Define 1-day intervals starting from 0:00 let stepsQuery = HKStatisticsCollectionQuery(quantityType: stepsCount!, quantitySamplePredicate: nil, options: .cumulativeSum, anchorDate: anchorDate!, intervalComponents: interval as DateComponents) // Set the results handler stepsQuery.initialResultsHandler = {query, results, error in let endDate = NSDate() let startDate = calendar.date(byAdding: .day, value: -7, to: endDate as Date, wrappingComponents: false) if let myResults = results{ myResults.enumerateStatistics(from: startDate!, to: endDate as Date) { statistics, stop in if let quantity = statistics.sumQuantity(){ let date = statistics.startDate let steps = quantity.doubleValue(for: HKUnit.count()) print("\(date): steps = \(steps)") //NOTE: If you are going to update the UI do it in the main thread DispatchQueue.main.async { //update UI components } } } //end block } //end if let } healthStore?.execute(stepsQuery) 

Ecco una traduzione che attualmente funziona per Swift 2.0, usando la libreria SwiftDate .

  let type = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount) let startDate = NSDate().beginningOfDay().oneWeekAgo() let interval = NSDateComponents() interval.day = 1 let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: NSDate(), options: .StrictStartDate) let query = HKStatisticsCollectionQuery(quantityType: type!, quantitySamplePredicate: predicate, options: [.CumulativeSum], anchorDate: NSDate().begginingOfDay(), intervalComponents:interval) query.initialResultsHandler = { query, results, error in let endDate = NSDate() let startDate = NSDate().beginningOfDay().oneWeekAgo() if let myResults = results{ myResults.enumerateStatisticsFromDate(startDate, toDate: endDate) { statistics, stop in if let quantity = statistics.sumQuantity() { let date = statistics.startDate let steps = quantity.doubleValueForUnit(HKUnit.countUnit()) print("\(date): steps = \(steps)") } } } } healthKitStore.executeQuery(query) 

Ho avvolto il mio in un blocco di completamento (objective -c). Ho trovato che era meglio impostare lo startDate per la query sulla data di oggi a mezzanotte. Spero che questo aiuti, sentiti libero di copiare / incollare per iniziare

 -(void)fetchHourlyStepsWithCompletionHandler:(void (^)(NSMutableArray *, NSError *))completionHandler{ NSMutableArray *mutArray = [NSMutableArray new]; NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar]; NSDate *startDate = [calendar dateBySettingHour:0 minute:0 second:0 ofDate:[NSDate date] options:0]; NSDate *endDate = [NSDate date]; // Whatever you need in your case HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; // Your interval: sum by hour NSDateComponents *intervalComponents = [[NSDateComponents alloc] init]; intervalComponents.hour = 1; // Example predicate NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate]; HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:type quantitySamplePredicate:predicate options:HKStatisticsOptionCumulativeSum anchorDate:startDate intervalComponents:intervalComponents]; query.initialResultsHandler = ^(HKStatisticsCollectionQuery *query, HKStatisticsCollection *results, NSError *error) { [results enumerateStatisticsFromDate:startDate toDate:endDate withBlock:^(HKStatistics *result, BOOL *stop) { if (!result) { if (completionHandler) { completionHandler(nil, error); } return; } HKQuantity *quantity = result.sumQuantity; NSDate *startDate = result.startDate; NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; formatter.dateFormat = @"ha"; NSString *dateString = [formatter stringFromDate:startDate]; double steps = [quantity doubleValueForUnit:[HKUnit countUnit]]; NSDictionary *dict = @{@"steps" : @(steps), @"hour" : dateString }; [mutArray addObject:dict]; }]; if (completionHandler) { completionHandler(mutArray, error); } }; [self.healthStore executeQuery:query]; 

}

Modificata la risposta di @ sebastianr usando le classi di base di Swift, solo per il test sto restituendo solo i passaggi per un solo giorno, una volta che hai più giorni puoi creare un dizionario di date e conteggio dei passi e restituirlo

 func getStepCountPerDay(completion:@escaping (_ count: Double)-> Void){ guard let sampleType = HKObjectType.quantityType(forIdentifier: .stepCount) else { return } let calendar = Calendar.current var dateComponents = DateComponents() dateComponents.day = 1 var anchorComponents = calendar.dateComponents([.day, .month, .year], from: Date()) anchorComponents.hour = 0 let anchorDate = calendar.date(from: anchorComponents) let stepsCumulativeQuery = HKStatisticsCollectionQuery(quantityType: sampleType, quantitySamplePredicate: nil, options: .cumulativeSum, anchorDate: anchorDate!, intervalComponents: dateComponents ) // Set the results handler stepsCumulativeQuery.initialResultsHandler = {query, results, error in let endDate = Date() let startDate = calendar.date(byAdding: .day, value: 0, to: endDate, wrappingComponents: false) if let myResults = results{ myResults.enumerateStatistics(from: startDate!, to: endDate as Date) { statistics, stop in if let quantity = statistics.sumQuantity(){ let date = statistics.startDate let steps = quantity.doubleValue(for: HKUnit.count()) print("\(date): steps = \(steps)") completion(steps) //NOTE: If you are going to update the UI do it in the main thread DispatchQueue.main.async { //update UI components } } } //end block } //end if let } HKHealthStore().execute(stepsCumulativeQuery) } 

Con la libreria aggiornata Swift 2.0 e SwiftDate .

 let type = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount) let startDate = NSDate().beginningOfDay let interval = NSDateComponents() interval.day = 1 let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: NSDate(), options: .StrictStartDate) let query = HKStatisticsCollectionQuery(quantityType: type!, quantitySamplePredicate: predicate, options: [.CumulativeSum], anchorDate: NSDate().beginningOfDay, intervalComponents:interval) query.initialResultsHandler = { query, results, error in let endDate = NSDate() let startDate = NSDate().beginningOfDay if let myResults = results{ myResults.enumerateStatisticsFromDate(startDate, toDate: endDate) { statistics, stop in if let quantity = statistics.sumQuantity() { let date = statistics.startDate let steps = quantity.doubleValueForUnit(HKUnit.countUnit()) print("\(date): steps = \(steps)") } } } } healthKitStore.executeQuery(query)