iOS Simulator Cannot Read the Health Data I Saved

Hi everyone!

I have created an app to save & read some running & walking workout data to HealthKit. I managed to save the data, and view it on the simulator's Health app, but when I try to read the data, sample count is 0. I'd appreciate if someone help me out with this.

Thanks in advance!

Xcode 12.5.1 / iOS 14.5

func AuthenticateHealthKit() {

  print("AuthenticateHealthKit")

  let typesToShare: Set = [
    HKQuantityType.workoutType()
  ]

  let typesToRead: Set = [
    HKQuantityType.workoutType(),
    HKQuantityType.quantityType(forIdentifier: .distanceWalkingRunning)!,
    HKQuantityType.quantityType(forIdentifier: .height)!,
  ]

  healthStore.requestAuthorization(toShare: typesToShare, read: typesToRead) { (success, error) in
    if !success {
      fatalError("Error requesting authorization from health store: \(String(describing: error)))")
    } else {
      print("Authenticated!")
    }
  }

}

func SaveData() {

  let configuration = HKWorkoutConfiguration()
  configuration.activityType = .running
  configuration.locationType = Int.random(in: 0..<2) == 0 ? .indoor : .outdoor

  let startDate = now - (86400 * 60.0)
  let duration = 120.0
  let endDate = startDate + duration
  let quantity = HKQuantity(unit: HKUnit.kilocalorie(), doubleValue: 20.0)
  let distance = HKQuantity(unit: HKUnit.meter(), doubleValue: 1200)

  let workout = HKWorkout(
    activityType: configuration.activityType, start: startDate, end: endDate, duration: duration,
    totalEnergyBurned: quantity, totalDistance: distance,
    metadata: [HKMetadataKeyIndoorWorkout: true])

  healthStore.save(workout) { success, _ in

    if success {
      print("SAVED WORKOUT!!!")
    } else {
      print("COULD NOT SAVE WORKOUT!!!")
    }

  }

}
func ReadData() {

  let start = now - (86400 * 60.0)
  let end = now
  let predicate = HKQuery.predicateForSamples(withStart: start, end: end, options: [])
  print("start : \(start)")

  guard HKHealthStore.isHealthDataAvailable() else {
    print("No data available!")
    return
  }

  guard
    let sampleType = HKSampleType.quantityType(
      forIdentifier: HKQuantityTypeIdentifier.distanceWalkingRunning)
  else {
    fatalError("*** This method should never fail ***")
  }

  let query = HKSampleQuery(
    sampleType: sampleType, predicate: predicate, limit: Int(HKObjectQueryNoLimit),
    sortDescriptors: nil
  ) {
    query, results, error in

    guard let samples = results as? [HKQuantitySample] else {
      print("Error")
      return
    }

    for sample in samples {
      print("sample : \(sample.quantity) \(sample.quantityType)")
    }

    DispatchQueue.main.async {
      print("Update UI : \(samples.count)")
    }
  }

  healthStore.execute(query)

}

Output of ReadData method

start : 2021-08-14 21:38:35 +0000
Authenticated!
Update UI : 0

Following are the Health App data & permissions (all on simulator)

Accepted Reply

You're writing workouts but wanting to read distance walking+running. Saving a distance property on workouts does not save a distance walking+running sample. You need to create a sample of that type, request auth for it, and save and associate with a workout using addSamples method on HKHealthStore.

It's much better to use an HKWorkoutBuilder and it's beginCollection/add/endCollection/finishWorkout methods which will create a proper HKWorkout object for you.

  • Thank you very much! I have managed to save the data with the help of your suggestion. I am adding the updated code as a comment for those who would come across the same question in the future.

Add a Comment

Replies

You're writing workouts but wanting to read distance walking+running. Saving a distance property on workouts does not save a distance walking+running sample. You need to create a sample of that type, request auth for it, and save and associate with a workout using addSamples method on HKHealthStore.

It's much better to use an HKWorkoutBuilder and it's beginCollection/add/endCollection/finishWorkout methods which will create a proper HKWorkout object for you.

  • Thank you very much! I have managed to save the data with the help of your suggestion. I am adding the updated code as a comment for those who would come across the same question in the future.

Add a Comment

I have managed to save data that I can successfully read with the ReadData method (look at the original question). This is the new SaveData method :

let now = Date()

func SaveData() {

        let configuration = HKWorkoutConfiguration()
        configuration.activityType = .running
        configuration.locationType = Int.random(in: 0..<2) == 0 ? .indoor : .outdoor

        let builder = HKWorkoutBuilder(healthStore: healthStore, configuration: configuration, device: .local())

        let sample = HKCumulativeQuantitySample(type: HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier.distanceWalkingRunning)!, quantity: HKQuantity.init(unit: HKUnit.meter(), doubleValue: 1230), start: now - 3600, end: now)

        builder.add([sample]) { success, error in

            guard success else {
                print("Error!")
                return
            }

            print("Added Sample")

        }

    }