'Inconsistent behavior using HKQueryAnchor in iOS 15?
I have this identical code running in 2 apps. In 1 app it works fine, in the other it always returns with 0, even when there are new workouts. Running both on an iPhone 13 Mini (iOS 15) If I pass in nil for HKAnchor then it returns all workouts so I know the problem is with the anchor. I can't really print out anything helpful to try and debug. Given this works in 1 app but not the other is there some other setting or Info.Plist field I need to add? I do have com.apple.developer.healthkit.background-delivery set to true.
private func updateWorkouts(completionHandler: @escaping () -> Void) {
var anchor = getAnchor()
if anchor == nil {
print("anchor is nil")
anchor = HKQueryAnchor(fromValue: Int(HKAnchoredObjectQueryNoAnchor))
}
let sampleType = HKObjectType.workoutType()
let workoutPredicate = HKQuery.predicateForWorkouts(with: .soccer)
let sourcePredicate = HKQuery.predicateForObjects(from: HKSource.default()) //limit query to only this app
let compound = NSCompoundPredicate(andPredicateWithSubpredicates: [workoutPredicate, sourcePredicate])
let anchoredQuery = HKAnchoredObjectQuery(type: sampleType, predicate: compound, anchor: anchor, limit: HKObjectQueryNoLimit) { [unowned self] query, newSamples, deletedSamples, newAnchor, error in
if let error = error {
print("error = \(error)")
}
print("anchoredQuery returned. New samples count = \(String(describing: newSamples?.count)) with new workout: \(String(describing: newSamples?.last?.startDate)) vs current date: \(Date()), new workout ID = \(String(describing: newSamples?.last?.uuid.uuidString))")
guard let unwrappedNewSamples = newSamples else { return }
guard unwrappedNewSamples.count > 0 else { return }
self.handleNewWorkouts(newWorkoutsAsSamples: unwrappedNewSamples, handler: { (success, error) in
self.currentlyConvertingWorkout = false
//We know we have all new workouts and are calculated, now we can save any info into Defaults we need
self.backgroundDataProcessor.processWorkouts(complete: { () in
self.saveAnchor(anchor: newAnchor!)
completionHandler()
})
})
}
healthStore.execute(anchoredQuery)
}
private func getAnchor() -> HKQueryAnchor? {
let encoded = UserDefaults.standard.data(forKey: AnchorKey)
guard let unwrappedEncoded = encoded else { return nil }
guard let anchor = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(unwrappedEncoded as Data) as? HKQueryAnchor
else {
print("error getting anchor")
return nil
}
return anchor
}
private func saveAnchor(anchor : HKQueryAnchor) {
do {
let encoded = try NSKeyedArchiver.archivedData(withRootObject: anchor, requiringSecureCoding: false)
print("saving anchor")
defaults.setValue(encoded, forKey: AnchorKey)
defaults.synchronize()
} catch {
print("problem with anchor")
return
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
