ios - funciona - HealthKit Swift consigue los pasos de hoy
healthkit data types (5)
Esta es la forma correcta de usar HKStatisticsCollectionQuery cortesía de la dirección del código anterior.
Esto está escrito en Swift 3, por lo que es posible que tenga que convertir parte del código a 2.3 o 2 si aún no está en 3.
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)
}
C objetivo
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];
Estoy creando una aplicación iOS rápida que se integra con el recuento de pasos de un usuario según lo informado por la aplicación Health. Puedo encontrar fácilmente el recuento de pasos del usuario en la última hora, usando esto como mi predicado:
let anHourBeforeNow: NSDate = NSDate().dateByAddingTimeInterval(-60 * 60)
let predicate = HKQuery.predicateForSamplesWithStartDate(anHourBeforeNow, endDate: NSDate(), options: .None)
Y tengo el resto hacia abajo, por lo que puedo acceder exitosamente al conteo de pasos del usuario durante la última hora. Pero, ¿cómo puedo acceder a los datos de pasos del usuario desde que comenzó el día, como muestra la aplicación Salud en la sección de pasos?
Estoy tratando de hacer algo como esto:
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)
let predicate = HKQuery.predicateForSamplesWithStartDate(newDate, endDate: NSDate(), options: .None)
pero este código no se ajusta a la zona horaria (por lo que me da el comienzo del día en UTC, no el comienzo del día en el que se encuentra el usuario) y también recibo conteos de pasos muy inflados (por razones desconocidas).
Entonces, ¿cómo puedo obtener el recuento de pasos del usuario para el día actual, con la misma cantidad de pasos que se informó en Salud, como se muestra aquí:
HKStatisticsCollectionQuery es más adecuado para usar cuando desea recuperar datos durante un período de tiempo. Use HKStatisticsQuery para obtener los pasos para una fecha específica.
Swift 4.2:
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)
}
La consulta que estaba usando toma todos los pasos registrados del usuario de Healthkit, no haciendo el filtro inteligente de los pasos duplicados que hace la aplicación Health. En su lugar, desea obtener los datos de pasos agregados que la aplicación de Salud produce después de combinar pasos de diferentes fuentes para obtener un recuento preciso.
Para hacer eso, puedes usar este código:
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)
}
Usando las respuestas anteriores y de Apple aquí: https://developer.apple.com/reference/healthkit/hkstatisticsquery Conseguí lo siguiente para trabajar en swift 2.3 en 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)
}
Para swift 4.2
1) Obtener 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) Para obtener los pasos cuentan para una fecha específica
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)
}
Cómo utilizar
self.getStepsCount(forSpecificDate: Date()) { (steps) in
if steps == 0.0 {
print("steps :: /(steps)")
}
else {
DispatchQueue.main.async {
print("steps :: /(steps)")
}
}
}