Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

HKAnchoredObjectQuery updateHandler stops working with error

Hi!

I am using the HKAnchoredObjectQuery to first get a snapshot of the initial results, and then trigger an updateHandler.

I need to handle the initial results and the updates separately, which is why I implemented two completions.

When I test the code, it works for a while. New and deleted samples trigger the updateHandler. However, after a while there appears an error:

[connection] nw_read_request_report [C2] Receive failed with error "Software caused connection abort"

Followingly, the updateHandler will stop getting triggered when I add updates in Apple health. Anyone have experience with this?

func getMostRecentSample(for sampleType: HKSampleType, 
anchorKey: String, 
completion: @escaping (HKQuantitySample?, Error?) -> Swift.Void, 
updateHandler: @escaping (HKQuantitySample, Error?) -> Swift.Void) {
    // If it is the first initialization, anchor is passed as nil
    var anchor: HKQueryAnchor? = nil
    // Check for previous saved anchor in userdefaults
    if UserDefaults.standard.object(forKey: anchorKey) != nil {
      let data = UserDefaults.standard.object(forKey: anchorKey) as! Data
      do {
        guard let newAnchor = try NSKeyedUnarchiver.unarchivedObject(ofClass: HKQueryAnchor.self, from: data) else {
          print("Could not parse anchor to HKQueryAnchor type")
          return
        }
        anchor = newAnchor
      } catch {
        print("Error retreiving anchor from UserDefaults")
      }
    }
    let query = HKAnchoredObjectQuery(type: sampleType,
                     predicate: nil,
                     anchor: anchor,
                     limit: HKObjectQueryNoLimit
                      ) { (query, samplesOrNil, _, newAnchor, errorOrNil) in
      guard let samples = samplesOrNil as? [HKQuantitySample] else {
        fatalError("*** An error occurred during the initial query: \(errorOrNil!.localizedDescription) ***")
      }
      if let anchor = newAnchor {
        do {
          let data = try NSKeyedArchiver.archivedData(withRootObject: anchor as Any, requiringSecureCoding: false)
          UserDefaults.standard.set(data, forKey: anchorKey)
        } catch {
          print("Error retreiving anchor from UserDefaults")
        }
      }
      completion(samples.last, nil)
    }
     
    // Setting up long-running query
    query.updateHandler = { (query, samplesOrNil, _, newAnchor, errorOrNil) in
      guard let samples = samplesOrNil as? [HKQuantitySample] else {
        fatalError("*** An error occurred during an update: \(errorOrNil!.localizedDescription) ***")
      }
      if let anchor = newAnchor {
        do {
          let data = try NSKeyedArchiver.archivedData(withRootObject: anchor as Any, requiringSecureCoding: false)
          UserDefaults.standard.set(data, forKey: anchorKey)
        } catch {
          print("Error retreiving anchor from UserDefaults")
        }
      }
      if let sample = samples.last {
        updateHandler(sample, nil)
      }
    }
    self.healthStore.execute(query)
  }

Update: The error was not due to the updateHandler as I thought, but due to another webAPI call.

I also discovered that the function works using datatypes with less data stored, while with datatypes like heart rate with high sample rate, the problem starts occuring. Maybe there is a timeout in the completion-handler? Prints inside of the query don't execute for datatypes with many samples.

Did you figure out what was going on? I have a recurrent issue with HKAnchoredQueryDescriptor and HeartRate Samples and I think perhaps its related?

HKAnchoredObjectQuery updateHandler stops working with error
 
 
Q