2016-09-23 4 views
4

Я создаю приложение для личного использования, и в настоящее время я зациклился на том, как точно получить вчерашние шаги из healthkit. И тогда оттуда, помещая его в переменную (должно быть легко, я знаю).Получение вчерашних шагов от HealthKit

У меня есть класс HealthKitManager, который вызывает функцию изнутри представления, а затем добавляет его к переменной из того же представления.

Я просмотрел большую часть вопросов healthKit, и я возвращаю данные, но я не думаю, что это точные данные. Данные моего телефона со вчерашнего дня - 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. Как я могу выполнить шаги из-за вчерашних шагов() и правильно разместить их в переменной в UpdateViewController?

Благодарим за помощь!

+0

У вас есть аккаунт с трекинговым трекером? –

+0

Каково ваше требование к приводу? Например, если пользователь добавляет шаги в healthkit вручную, вы хотите также прочитать или нет? –

+0

На моем телефоне нет сторонних трекеров, и необходимо просто прочитать шаги из приложения для здоровья телефона. Не нужно вручную добавлять шаги, либо – mint

ответ

6

Это метод я использую в моем healthStore классе

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

Надеюсь, это поможет. Дайте мне знать, если вы столкнетесь с какой-либо проблемой.

+0

работает отлично! Просто предупреждение для других, у кого может быть такая же проблема: если у вас есть метки, связанные с обновляемыми переменными после функции, в которой вы получаете данные, они могут обновляться до завершения запроса, поэтому он будет выглядеть так, как будто он не обновлялся , Добавление NSTimer, обновлявшего метки после 2 секунд, работало для меня – mint