Julius
Julius

Reputation: 509

HealthKit anchored queries with fallback methods?

I need to synchronize my app's database with HealthKit, and I'm currently using HKAnchoredObjectQuery to receive only the recent data. My deployment target is iOS 8.0, but I wanted to implement a fallback method to have better support for iOS 9.0+ as well. Here's the current code:

func synchronize(sampleType: HKSampleType) {

    if #available(iOS 9.0, *) {

        let queryAnchor = HKQueryAnchor(fromValue: self.anchor)
        let resultsHandler: (HKAnchoredObjectQuery, [HKSample]?, [HKDeletedObject]?, HKQueryAnchor?, NSError?) -> Void = {
            query, newSamples, deletedSamples, newAnchor, error in

            // Handle results here
            // TODO: QueryAnchor should persist in order to receive only new data changes!
        }

        let query = HKAnchoredObjectQuery(type: sampleType,
                                          predicate: nil,
                                          anchor: queryAnchor,
                                          limit: HKObjectQueryNoLimit,
                                          resultsHandler: resultsHandler)

        healthKitStore.executeQuery(query)

    } else {

        // Fallback on earlier versions
        let completionHandler: (HKAnchoredObjectQuery, [HKSample]?, Int, NSError?) -> Void = {
            query, results, newAnchor, error in

            // Handle results here
            self.anchor = newAnchor
        }

        let query = HKAnchoredObjectQuery(type: sampleType,
                                          predicate: nil,
                                          anchor: self.anchor,
                                          limit: HKObjectQueryNoLimit,
                                          completionHandler: completionHandler)

        healthKitStore.executeQuery(query)
    }
}

Two issues:

  1. I don't know how to persist the HKQueryAnchor, because iOS 8 doesn't support it. I'm supposed to update the persisted variable to the new anchor object the query handler returns. If I could somehow convert it to Int, I could store it as a class variable, but I don't know how.

  2. The deprecated initializer for HKAnchoredObjectQuery uses a handler that doesn't return deleted objects. Does this mean I cannot track deleted HKSamples in iOS 8?

Upvotes: 0

Views: 530

Answers (1)

goldengil
goldengil

Reputation: 1037

Regarding the first issue, HKQueryAnchor was introduced on iOS 9 and indeed isn't available on iOS 8. However, reading the documentation of it yields it conforms to NSSecureCoding which mean you can store it in a user defaults for persistence. So you can manage a dictionary that contain a key of the relevant type identifier and a value of the corresponded HKQueryAnchor on iOS 9, while on iOS 8 manage the same list with an NSNumber that holds the anchor value.

For backwards compatibility you can use the anchorFromValue: class method of HKQueryAnchor to convert old anchor values to the new class.

Regarding your second question, as far as I know there isn't a straightforward way of tracking deleted HKSamples on iOS 8. You can learn more about the way of doing it on iOS 9 in session 203 of WWDC2015

Upvotes: 2

Related Questions