2015-04-11 11 views
6

Qual è il modo migliore per ottenere un conteggio totale dei passi 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.Ottieni il conteggio totale dei passaggi per ogni data in HealthKit

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

Credo di poter interrogare tutti i conteggi step registrati e passare attraverso la matrice e calcolare il numero totale di passaggio per ogni giorno, ma spero in una soluzione più facile in quanto ci saranno migliaia di oggetti HKSampleQuery. C'è un modo per avere initWithSampleType restituire un numero totale di passi al giorno?

risposta

14

Si dovrebbe usare 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]; 
+0

Grazie, questo era esattamente quello che stavo cercando! – MathiasMo

+0

Sembra fantastico. Ho cercato di tradurre rapidamente senza successo. Qualcuno ha una traduzione? – dstefanis

+0

@dstefanis l'ho tradotto in modo rapido. non so se è troppo tardi. Saluti. – horsejockey

1

Ecco una traduzione che attualmente lavora per Swift 2.0, utilizzando 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) 
+0

Come leggere i dati della frequenza cardiaca dal kit di salute di Apple? –

+2

Non penso che sia una buona idea dare una traduzione Swift che richiede una libreria aggiuntiva - ma senza offesa – arnoapp

-1

Con Aggiornato Swift 2.0 & SwiftDate biblioteca.

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

Port a Swift con alcuna dipendenza alla 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) 
0

ho avvolto la mia in un blocco di completamento (-c oggettiva). Ho trovato che era meglio impostare lo startDate per la query sulla data di oggi a mezzanotte. Spero che questo aiuti, si sentono liberi 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 = @"h a"; 


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

}

0

Modified risposta di @ sebastianr usando fondamentali classi Swift, solo per i test Sto tornando a pochi passi per un solo giorno, una volta che si avere più giorni è possibile 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) 
} 
Problemi correlati