Vedd
Vedd

Reputation: 35

Works fine when healthkit access was previously authorized on device but crashes otherwise

override func viewDidLoad() {
    super.viewDidLoad()
    ref = Database.database().reference()
    let healthKitTypes: Set = [
        // access step count
        HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
    ]
    healthStore.requestAuthorization(toShare: healthKitTypes, read: healthKitTypes) { (_, _) in
        print("authorized???")
    }
    healthStore.requestAuthorization(toShare: healthKitTypes, read: healthKitTypes) { (bool, error) in
        if let e = error {
            print("oops something went wrong during authorization \(e.localizedDescription)")
        } else {
            print("User has completed the authorization flow")
        }
    }


    getTodaysSteps { (result) in
        print("\(result)")
        self.steps = result

        DispatchQueue.main.async {
            if result == 0 {
                self.StepDisplay.text = " You haven't walked"
            } else {
                self.StepDisplay.text = "\(result)"
            }

        }
    }


    getStepHistory()



}


func getStepHistory() {
    let calendar = Calendar.current
    var interval = DateComponents()
    interval.day = 1

    // Set the anchor date to Monday at 3:00 a.m.
    var anchorComponents = calendar.dateComponents([.day, .month, .year, .weekday], from: Date())


    let offset = (7 + (anchorComponents.weekday ?? 0) - 2) % 7
    anchorComponents.day = (anchorComponents.day ?? 0) - offset
    anchorComponents.hour = 0
    anchorComponents.minute = 1

    guard let anchorDate = calendar.date(from:anchorComponents) else {
        fatalError("*** unable to create a valid date from the given components ***")
    }

    guard let quantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount) else {
        fatalError("*** Unable to create a step count type ***")
    }

This code works fine when the authorization is already given on the device. If however, it was not authorized earlier, it will not work unless getStepHistory() is commented out in viewDidLoad. I tried requesting additional authorization from within the getStepHistory() function but it doesn't solve the problem

Upvotes: 1

Views: 232

Answers (2)

Rahul Umap
Rahul Umap

Reputation: 2859

Requesting the User's Permission

To request authorization, we invoke

requestAuthorization(toShare:,readTypes:,completion:) on the HKHealthStore instance. This method accepts three parameters:

  • an optional set of HKSampleType objects
  • an optional set of HKObjectType objects
  • a completion handler with two parameters, a boolean indicating the result of the authorization request (successful or unsuccessful) and an optional error

It is important to understand that the boolean of the completion handler does not indicate whether the user granted or denied access to the requested health data types. It only informs the application whether the user responded to the application's authorization request. If the user dismissed the form by canceling the authorization request, the boolean of the completion handler is set to false.

In Your View Did Load :

healthStore.requestAuthorization(toShare: healthKitTypes, read: healthKitTypes) { (success, error) in
    if let err = error {
        print("Error \(err.localizedDescription)")
    } else if success {
        // Get the Step Count....
        getStepHistory()
    } else {
        print("No access to healthkit data")
    }
}

Optionally You can try this function to get step count:

    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)
    }

Upvotes: 1

rmaddy
rmaddy

Reputation: 318774

You need to call getStepHistory inside the completion block to requestAuthorization if it has been authorized.

healthStore.requestAuthorization(toShare: healthKitTypes, read: healthKitTypes) { (success, error) in
    if let e = error {
        print("oops something went wrong during authorization \(e.localizedDescription)")
    } else if success {
        print("User has granted access")
        getStepHistory()
    } else {
        print("User has completed the authorization flow but there is no access")
    }
}

Upvotes: 2

Related Questions