Get total step count for every date in HealthKit

后端 未结 6 535
南笙
南笙 2020-11-29 06:13

What\'s the best way to get a total step count for every day recorded in HealthKit. With HKSampleQuery\'s method initWithSampleType (see below) I can set a star

相关标签:
6条回答
  • 2020-11-29 06:40

    I wrapped mine in a completion block (objective -c). I found what was best was to set the startDate for the query to todays date at midnight. Hope this helps, feel free to copy/paste to get started

    -(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 讨论(0)
  • 2020-11-29 06:41

    Port to Swift with no dependency to SwiftDate library

        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 讨论(0)
  • 2020-11-29 06:43

    With Updated Swift 2.0 & SwiftDate library.

    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)
    
    0 讨论(0)
  • 2020-11-29 06:57

    You should use 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 讨论(0)
  • 2020-11-29 07:00

    Modified @sebastianr's answer using core Swift classes, for just for testing I am returning only steps for just one day, once you have more days you can create a dictionary of Dates and step count and return it

    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)
    }
    
    0 讨论(0)
  • 2020-11-29 07:00

    Here is a translation that currently works for Swift 2.0, using the SwiftDate library.

        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 讨论(0)
提交回复
热议问题