从 HealthKit 获取昨天的步数

Getting yesterdays steps from HealthKit

我正在构建一个供个人使用的应用程序,目前我正在研究如何从 healthkit 中准确获取昨天的步数。然后从那里,将它放入一个变量中(应该很容易,我知道)。

我有一个 HealthKitManager class 从视图内部调用函数,然后将其附加到同一视图中的变量。

我已经搜索了大部分的 healthKit 问题,并且得到了数据,但我认为它不是准确的数据。我昨天的 phone 数据是 1442 步,但它返回了 2665 步。最重要的是,当我尝试将数据放入变量时,它打印为 0.

HealthKitManagerClass

import Foundation
import HealthKit

class HealthKitManager {
let storage = HKHealthStore()

init()
{
    checkAuthorization()
}

func checkAuthorization() -> Bool
{
    // Default to assuming that we're authorized
    var isEnabled = true

    // Do we have access to HealthKit on this device?
    if HKHealthStore.isHealthDataAvailable()
    {
        // We have to request each data type explicitly
        let steps = NSSet(object: HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount)!)

        // Now we can request authorization for step count data
        storage.requestAuthorizationToShareTypes(nil, readTypes: steps as? Set<HKObjectType>) { (success, error) -> Void in
            isEnabled = success
        }
    }
    else
    {
        isEnabled = false
    }

    return isEnabled
}

func yesterdaySteps(completion: (Double, NSError?) -> ())
{
    // The type of data we are requesting (this is redundant and could probably be an enumeration
    let type = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount)

    // Our search predicate which will fetch data from now until a day ago
    // (Note, 1.day comes from an extension
    // You'll want to change that to your own NSDate

    let calendar = NSCalendar.currentCalendar()
    let yesterday = calendar.dateByAddingUnit(.Day, value: -1, toDate: NSDate(), options: [])

    //this is probably why my data is wrong
    let predicate = HKQuery.predicateForSamplesWithStartDate(yesterday, endDate: NSDate(), options: .None)

    // The actual HealthKit Query which will fetch all of the steps and sub 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())
            }
        }

        //I'm unsure if this is correct as well
        completion(steps, error)
        print("\(steps) STEPS FROM HEALTH KIT")
        //this adds the steps to my character (is this in the right place)
        Player.User.Gold.addSteps(Int(steps))
    }
    //not 100% on what this does, but I know it is necessary
    storage.executeQuery(query)
}}

ViewControllerClass

import UIKit
import Foundation

class UpdateViewController: UIViewController {

@IBOutlet var back: UIButton!

let HKM = HealthKitManager()
var stepsFromPhone = Double()


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    back.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))


    HKM.yesterdaySteps(){ steps, error in
       self.stepsFromPhone = steps
    }

    Player.User.Gold.addSteps(Int(stepsFromPhone))
    print(Player.User.Gold.getSteps(), "IN PLAYER")

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

来自

的输出
print(Player.User.Gold.getSteps(), "IN PLAYER")

0 IN PLAYER

来自

的输出
print("\(steps) STEPS FROM HEALTH KIT")

2665.0 STEPS FROM HEALTH KIT

所以,基本上我的问题是:

  1. 整个昨天我需要什么 NSDate()?
  2. 如何从 yesterdaySteps() 中获取步骤并将它们正确地放入 UpdateViewController 中的变量中?

感谢您的帮助!

这是我在 healthStore 中使用的方法 class

    func TodayTotalSteps(completion: (stepRetrieved: Double) -> Void) {

    let type = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount) // The type of data we are requesting

    let calendar = NSCalendar.currentCalendar()
    let interval = NSDateComponents()
    interval.day = 1

    let anchorComponents = calendar.components([.Day , .Month , .Year], fromDate: NSDate())
    anchorComponents.hour = 0
    let anchorDate = calendar.dateFromComponents(anchorComponents)

    let stepsQuery = HKStatisticsCollectionQuery(quantityType: type!, quantitySamplePredicate: nil, options: .CumulativeSum, anchorDate: anchorDate!, intervalComponents: interval)

    stepsQuery.initialResultsHandler = {query, results, error in
        let endDate = NSDate()

        var steps = 0.0
        let startDate = calendar.dateByAddingUnit(.Day, value: 0, toDate: endDate, options: [])
        if let myResults = results{  myResults.enumerateStatisticsFromDate(startDate!, toDate: endDate) { statistics, stop in
            if let quantity = statistics.sumQuantity(){
                let date = statistics.startDate
                steps = quantity.doubleValueForUnit(HKUnit.countUnit())
               // print("\(date): steps = \(steps)")
            }

            completion(stepRetrieved: steps)
            }
        } else {

            completion(stepRetrieved: steps)
        }
    }
    executeQuery(stepsQuery)
}

下面是我的使用方法

func getStepsData() {

   // I am sendng steps to my server thats why using this variable
    var stepsToSend = 0

        MyHealthStore.sharedHealthStore.todayManuallyAddedSteps({ (steps , error) in
            if error != nil{
                // handle error
            }
            else{
                // truncating manuall steps
                MyHealthStore.sharedHealthStore.TodayTotalSteps({ (stepRetrieved) in
                    stepsToSend =  Int(stepRetrieved - steps)
                })
            }
        })
}

这里是上面用于手动添加的步骤的函数,我们正在截断这些步骤以获得准确的步骤

    func todayManuallyAddedSteps(completion: (Double, NSError?) -> () )
{
    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]
            {

                // checking and adding manually added steps
                if result.sourceRevision.source.name == "Health" {
                    // these are manually added steps

                    steps += result.quantity.doubleValueForUnit(HKUnit.countUnit())
                }
                else{
                    // these are auto detected steps which we do not want from using HKSampleQuery
                }
            }
            completion(steps, error)
        } else {
            completion(steps, error)
        }
    }
    executeQuery(query)
}

希望对您有所帮助。如果您遇到任何问题,请告诉我。

您可以使用HKStatisticsQuery

let quantityType = HKSampleType.quantityType(forIdentifier: .stepCount)!

let predicate = HKQuery.predicateForSamples(
  withStart: startDate,
  end: endDate,
  options: [.strictStartDate, .strictEndDate]
)

let query = HKStatisticsQuery(
  quantityType: quantityType,
  quantitySamplePredicate: predicate,
  options: .cumulativeSum) { (query, result, error) in
    guard let result = result, error == nil else {
      print("HeathService error \(String(describing: error))")
      return
    }

    callback(result)
}