Je crée une application Swift iOS qui s'intègre au nombre d'étapes d'un utilisateur tel que rapporté par l'application Health. Je peux facilement trouver le nombre de pas de l'utilisateur au cours de la dernière heure, en utilisant ceci comme prédicat:
let anHourBeforeNow: NSDate = NSDate().dateByAddingTimeInterval(-60 * 60)
let predicate = HKQuery.predicateForSamplesWithStartDate(anHourBeforeNow, endDate: NSDate(), options: .None)
Et j'ai le reste, afin que je puisse accéder avec succès au nombre de pas de l'utilisateur pour la dernière heure. Mais comment puis-je accéder aux données des étapes de l'utilisateur depuis le début de la journée, comme dans l'application Health (Santé), dans la section des étapes?
J'essaie de faire quelque chose comme ça:
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)
let predicate = HKQuery.predicateForSamplesWithStartDate(newDate, endDate: NSDate(), options: .None)
mais ce code ne s'adapte pas au fuseau horaire (il me donne donc le début de la journée en UTC, pas le début de la journée où se trouve l'utilisateur) et j'obtiens également des comptes de pas très gonflés (pour des raisons inconnues).
Alors, comment puis-je obtenir le nombre de pas de l'utilisateur pour le jour en cours, avec le même nombre de pas que celui indiqué dans Santé, comme illustré ci-dessous:
Voici la bonne façon d'utiliser HKStatisticsCollectionQuery avec la courtoisie du code ci-dessus.
Ceci est écrit dans Swift 3, vous devrez donc peut-être reconvertir une partie du code en 2.3 ou 2 sinon sur 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)
}
Objectif 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];
HKStatisticsCollectionQuery est mieux adapté lorsque vous souhaitez récupérer des données sur une période donnée. Utilisez HKStatisticsQuery pour obtenir simplement les étapes pour une date spécifique.
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 requête que vous utilisiez utilise toutes les étapes enregistrées par l'utilisateur dans Healthkit, et non le filtrage intelligent des étapes en double effectuées par l'application Health. Au lieu de cela, vous souhaitez obtenir les données d'étape agrégées que l'application Santé produit après avoir combiné des étapes provenant de différentes sources pour obtenir un décompte précis.
Pour ce faire, vous pouvez utiliser ce 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)
}
Pour Swift 4.2
1) Obtenir 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) Pour que les étapes comptent pour une date spécifique
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)
}
Comment utiliser
self.getStepsCount(forSpecificDate: Date()) { (steps) in
if steps == 0.0 {
print("steps :: \(steps)")
}
else {
DispatchQueue.main.async {
print("steps :: \(steps)")
}
}
}
Si vous souhaitez obtenir le nombre total d'étapes pour chaque jour, sur une période donnée, utilisez/ HKStatisticsCollectionQuery , code dans 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)
En utilisant les réponses ci-dessus et de Apple, cliquez ici: https://developer.Apple.com/reference/healthkit/hkstatisticsquery J'ai obtenu ce qui suit pour travailler dans Swift 2.3 sur 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)
}