In my current project, I need to sync with HealthKit samples with my application. I am fetching sample data from HealthKit and writing some app generated samples back to HealthKit. For fetching I'm using the following function:-
private func readHealthKitSample(sampleType:HKSampleType, limit: Int, startDate: NSDate, endDate: NSDate, completion: (([HKSample]?, NSError!) -> Void)!){
let mostRecentPredicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate:endDate, options: .None)
// 2. Build the sort descriptor to return the samples in descending order
let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate, ascending: false)
// 3. we want to limit the number of samples returned by the query to just 1 (the most recent)
let limit = limit
// 4. Build samples query
let sampleQuery = HKSampleQuery(sampleType: sampleType, predicate: mostRecentPredicate, limit: limit, sortDescriptors: [sortDescriptor])
{ (sampleQuery, results, error ) -> Void in
if let error = error {
self.Logger.error("HealthKit Sample Data Fetch Error: \(error.localizedDescription)")
completion(nil , error)
return;
} else {
// self.Logger.debug("HealthKit Sample Data Fetch SUCCESS: \(results)")
}
// Execute the completion closure
if completion != nil {
completion(results,nil)
}
}
// 5. Execute the Query
self.healthKitStore.executeQuery(sampleQuery)
}
My app requires not to consider the samples written by itself to HealthKit Store. So, is there a way to filter sample data in a such way that I can avoid receiving them written by my application and consider only those samples written by other apps?
You can use HKSource to filter out your own app and NSCompoundPredicate to combine this with your existing predicate filter:
let mostRecentPredicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate:endDate, options: .None)
let myAppPredicate = HKQuery.predicateForObjectsFromSource(HKSource.defaultSource()) // This would retrieve only my app's data
let notMyAppPredicate = NSCompoundPredicate(notPredicateWithSubpredicate: myAppPredicate) // This will retrieve everything but my app's data
let queryPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [mostRecentPredicate, notMyAppPredicate])
let sampleQuery = HKSampleQuery(sampleType: sampleType, predicate: queryPredicate, limit: limit, sortDescriptors: [sortDescriptor]) {
// Process results here...
}
Swift 5+:
let mostRecentPredicate = HKQuery.predicateForSamples(withStart: startDate, end:endDate, options: [])
let myAppPredicate = HKQuery.predicateForObjects(from: HKSource.default()) // This would retrieve only my app's data
let notMyAppPredicate = NSCompoundPredicate(notPredicateWithSubpredicate: myAppPredicate) // This will retrieve everything but my app's data
let queryPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [mostRecentPredicate, notMyAppPredicate])
let sampleQuery = HKSampleQuery(sampleType: sampleType, predicate: queryPredicate, limit: limit, sortDescriptors: [sortDescriptor]) {
// Process results here...
}