Mxyb
Mxyb

Reputation: 415

How do I ignore manually added data in HealthKit?

I want to get the step data of a user by using HealthKit. However, I want to make sure that data that has been entered manually is ignored. I found a solution where someone asked this question and I know what needs to be entered but I am unsure how to do this. Wherever I put this code I seem to get errors:

Here is my code:

   func calculateSteps(completion: @escaping (HKStatisticsCollection?)-> Void) {
        
        let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
        
        let startDate = Calendar.current.date(byAdding: .day, value: -7, to: Date())
        
        let anchorDate = Date.mondayAt12AM()
        
        let daily = DateComponents(day: 1)
        
        let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictStartDate)
        
        query = HKStatisticsCollectionQuery(quantityType: stepType, quantitySamplePredicate: predicate, options: .cumulativeSum, anchorDate: anchorDate, intervalComponents: daily)
        
        query!.initialResultsHandler = { query, statisticsCollection, error in
            completion(statisticsCollection)
            
        }
        
        if let healthStore = healthStore, let query = self.query {
            healthStore.execute(query)
        }
    }

And this is the sort of code I need to implement in the predicate part.

let predicate = NSPredicate(format: "metadata.%K != YES", HKMetadataKeyWasUserEntered)

Where shall I put this code?

UPDATED: I have the code running with no errors however when the function runs it comes out as 0. Any ideas?

import Foundation
import HealthKit

extension Date {
    static func mondayAt12AM() -> Date {
        return Calendar(identifier: .iso8601).date(from: Calendar(identifier: .iso8601).dateComponents([.yearForWeekOfYear, .weekOfYear], from: Date()))!
    }
}

class HealthStore {
    
    var healthStore: HKHealthStore?
    var query: HKStatisticsCollectionQuery?
    
    init() {
        if HKHealthStore.isHealthDataAvailable() {
            healthStore = HKHealthStore()
            
        }
    }

    func calculateSteps(completion: @escaping (HKStatisticsCollection?)-> Void) {
        
        let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
        
        let startDate = Calendar.current.date(byAdding: .day, value: -7, to: Date())
        
        let anchorDate = Date.mondayAt12AM()
        
        let daily = DateComponents(day: 1)
        
       
        
        let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictStartDate)
        let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates:
                                    [.init(format: "metadata.%K == NO", HKMetadataKeyWasUserEntered), predicate]
                                )
        query = HKStatisticsCollectionQuery(
           quantityType: stepType,
           quantitySamplePredicate: compoundPredicate,
           options: .cumulativeSum,
           anchorDate: anchorDate,
           intervalComponents: daily)
        
             
        
        query!.initialResultsHandler = { query, statisticsCollection, error in
            completion(statisticsCollection)
            
        }
        
        if let healthStore = healthStore, let query = self.query {
            healthStore.execute(query)
        }
    }
    
    func requestAuthorization(completion: @escaping (Bool) -> Void) {
        
        let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
        
        guard let healthStore = self.healthStore else { return completion(false) }
        
        healthStore.requestAuthorization(toShare: [], read: [stepType]) { (success, error) in
            completion(success)
        }
    }
}

Upvotes: 1

Views: 592

Answers (3)

gggava
gggava

Reputation: 266

Create a compound predicate with your current predicate

var predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: [.strictStartDate])
let predicateAvoidManuallyLoggedData = HKQuery.predicateForObjects(withMetadataKey: HKMetadataKeyWasUserEntered, operatorType: .notEqualTo, value: true)
predicate = NSCompoundPredicate(andPredicateWithSubpredicates:[predicateAvoidManuallyLoggedData, predicate])

query = HKStatisticsCollectionQuery(
   quantityType: stepType,
   quantitySamplePredicate: compountPredicate,
   options: .cumulativeSum,
   anchorDate: anchorDate,
   intervalComponents: daily)

Upvotes: 1

Bhavik Thummar
Bhavik Thummar

Reputation: 11

You need to create one Compound Predicate with the current Predicate as sub Predicate. And in format set metadata.%K != YES (metadata.%K == NO will not work here, because the value for the key could be YES, NO, or nil and nil implies NO).

And then create a query using that Compound Predicate.

Here is the code Sample

let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
    
let startDate = Calendar.current.date(byAdding: .day, value: -7, to: Date())!
    
let daily = DateComponents(day: 1)
    
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictStartDate)
    let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [.init(format: "metadata.%K != YES", HKMetadataKeyWasUserEntered), predicate])
    
let query = HKStatisticsCollectionQuery(quantityType: stepType, quantitySamplePredicate: compoundPredicate, options: .cumulativeSum, anchorDate: startDate, intervalComponents: daily)

Upvotes: 1

vk0425
vk0425

Reputation: 36

I would try to create an NSCompoundPredicate with both the predicates you want and use that while creating the query.

If you are still running into errors, please share the specific errors you see.

Upvotes: 0

Related Questions