簡體   English   中英

HealthKit Swift 邁出了今天的步伐

[英]HealthKit Swift getting today's steps

我正在制作一個快速的 iOS 應用程序,它與 Health 應用程序報告的用戶步數集成。 我可以很容易地找到用戶在過去一小時內的步數,使用它作為我的謂詞:

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 中一天的開始,而不是用戶所在的一天的開始),而且我的步數計數也非常高(原因未知)。

那么如何獲取用戶當天的步數,其步數與 Health 中報告的步數相同,如下圖所示: 在此處輸入圖片說明

HKStatisticsCollectionQuery 更適合在您想要檢索一段時間內的數據時使用。 使用 HKStatisticsQuery 來獲取特定日期的步驟。

斯威夫特 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)
}

這是根據上面代碼的方向使用 HKStatisticsCollectionQuery 的正確方法。

這是用 Swift 3 編寫的,因此您可能需要將某些代碼轉換回 2.3 或 2,如果還不是 3。

斯威夫特 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)
    }

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

對於快速 4.2

1) 獲取 HealthKit 權限

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

如果您想獲得一段時間內每天的總步數,請使用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)

您使用的查詢從 Healthkit 獲取用戶記錄的所有步驟,而不是對 Health 應用程序執行的重復步驟進行智能過濾。 相反,您希望獲得 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)
}

使用上面的答案和來自 Apple 的答案: https : //developer.apple.com/reference/healthkit/hkstatisticsquery我得到了以下內容,可以在 Xcode 8.0 上的 swift 2.3 中工作。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM