'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