Myk
Myk

Reputation: 1019

How to query for samples from health kit that have an HKDevice

I want to query samples from HealthKit but in order to prevent inaccurate or manipulated data I don't want samples that were written to health by other apps. Does anyone have any idea what predicate I can use to filter out data from all apps or to only allow data from devices? Thanks in advance.

Edit: I've realized that apps can save data to health with an HKDevice included. So filtering out samples that don't have devices won't work.

Upvotes: 1

Views: 2279

Answers (3)

Mohammad Rahchamani
Mohammad Rahchamani

Reputation: 5220

You can filter out the results that are not stored by apple in your query instead of iterating all the results.

first, you need to get all the sources for your desired type.

let query = HKSourceQuery(sampleType: type,
                                  samplePredicate: predicate) {
                                    query, sources, error in
                                    
                                    // error handling ...
                                    
                                    // create a list of your desired sources
                                    let desiredSources = sources?.filter { 
                                          !$0.bundleIdentifier.starts(with: "com.apple.health")
                                     }
                                    
                                    // now use that list as a predicate for your query
                                    let sourcePredicate = HKQuery.predicateForObjects(from: desiredSources!)

                                    // use this predicate to query for data

        }
        

you can also combine other predicates using NSCompoundPredicate

Upvotes: 1

Allan
Allan

Reputation: 7363

If what you want to do is exclude manually entered data, see this answer: Ignore manual entries from Apple Health app as Data Source

Samples that were added to HealthKit by the user via Health will have the HKMetadataKeyWasUserEntered key.

Upvotes: 1

Myk
Myk

Reputation: 1019

I'm still open to suggestions and alternate solutions but here is my work-around since I was unable to figure out how to use a predicate to get the job done.

 let datePredicate = HKQuery.predicateForSamples(withStart:Date(), end: nil, options: [])

 let sampleQuery = HKAnchoredObjectQuery(type: sampleType,
                                               predicate: predicate,
                                               anchor: nil,
                                               limit: Int(HKObjectQueryNoLimit)) { query,
                                                                                   samples,
                                                                                   deletedObjects,
                                                                                   anchor,
                                                                                   error in
        if let error = error {
            print("Error performing sample query: \(error.localizedDescription)")
            return
        }

        guard let samples = samples as? [HKQuantitySample] else { return }

        // this line filters out all samples that do not have a device
        let samplesFromDevices = samples.filter { 
            $0.device != nil && $0.sourceRevision.source.bundleIdentifier.hasPrefix("com.apple.health") 
        }
        doStuffWithMySamples(samplesFromDevices)
    }

As you can see, I just filter the data once it comes through rather than doing it before-hand.

Edit: Seems like the sources listed in health are separated into apps and actual devices. Not 100% sure how they do this but it seems like the sources under the device section all have a bundle identifier prefixed with com.apple.health. Hopefully this works.

Upvotes: 0

Related Questions