HealthKit Swift getting today's steps

后端 未结 6 1479
灰色年华
灰色年华 2020-12-23 11:50

I am making a swift iOS app that integrates with a user\'s step count as reported by the Health app. I can easily find the user\'s step count in the last hour, using this as

相关标签:
6条回答
  • 2020-12-23 12:24

    Using the above answers and from Apple here: https://developer.apple.com/reference/healthkit/hkstatisticsquery I got the following to work in swift 2.3 on 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)
            }
    
    0 讨论(0)
  • 2020-12-23 12:29

    Here is the right way using HKStatisticsCollectionQuery courtesy of the direction from the code above.

    This is written in Swift 3 so you may have to convert some of the code back to 2.3 or 2 if not on 3 yet.

    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];
    
    0 讨论(0)
  • 2020-12-23 12:38

    If you want to get the total number of step for each day, over a period of time, then use HKStatisticsCollectionQuery, code in 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)
    
    0 讨论(0)
  • 2020-12-23 12:45

    The query you were using takes all of the user's recorded steps from Healthkit, not doing the smart filter-out of duplicative steps the Health app does. Instead, you want to get the aggregated step data that the Health app produces after combining steps from different sources to get an accurate tally.

    To do that, you can use this code:

    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)
    }
    
    0 讨论(0)
  • 2020-12-23 12:45

    For swift 4.2

    1) Get 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) To get steps count for specific date

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

    How to use

    self.getStepsCount(forSpecificDate: Date()) { (steps) in
                    if steps == 0.0 {
                        print("steps :: \(steps)")
                    }
                    else {
                        DispatchQueue.main.async {
                            print("steps :: \(steps)")
                        }
                    }
                }
    
    0 讨论(0)
  • 2020-12-23 12:47

    HKStatisticsCollectionQuery is better suited to use when you want to retrieve data over a time span. Use HKStatisticsQuery to just get the steps for a specific date.

    Swift 5:

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