Looks like the issue has been fixed in iOS 18.1 (22B5034e) Developer Beta.
Post
Replies
Boosts
Views
Activity
I've faced a similar issue while fetching today's steps from HealthKit. I've managed to fix it by creating a predicate using HKQuery.predicateForSamples(withStart:end:options:) and using the .strictStartDate query option. The predicate is then passed to the HKStatisticsCollectionQuery initialiser. Here's an example how to fetch today's current steps and subscribe to updates with this approach:
/// Fetches today's total steps and subscribes to all future changes of this value
/// - Parameter onUpdate: callback which is called on the initial fetch and every time the value changes in the future
func subscribeToStepUpdates(onUpdate: @escaping (Int?) -> Void) {
func finishWithResult(_ value: Int?) {
DispatchQueue.main.async {
onUpdate(value)
}
}
guard let type = HKQuantityType.quantityType(forIdentifier: .stepCount) else {
finishWithResult(nil)
return
}
// set the anchor for 0 a.m.
let components = DateComponents(calendar: Calendar.current, timeZone: Calendar.current.timeZone, hour: 0, minute: 0, second: 0)
guard let anchorDate = Calendar.current.nextDate(
after: Date(),
matching: components,
matchingPolicy: .nextTime,
repeatedTimePolicy: .first,
direction: .backward
) else {
finishWithResult(nil)
return
}
let predicate = HKQuery.predicateForSamples(withStart: Calendar.current.startOfDay(for: Date()), end: nil, options: [.strictStartDate])
let query = HKStatisticsCollectionQuery(
quantityType: type,
quantitySamplePredicate: predicate,
options: .cumulativeSum,
anchorDate: anchorDate,
intervalComponents: DateComponents(day: 1)
)
// initial response
query.initialResultsHandler = { [weak self] _, result, error in
guard
error == nil,
let statsCollection = result
else {
finishWithResult(nil)
return
}
let endDate = Date()
let startDate = Calendar.current.startOfDay(for: endDate)
var resultCount = 0
statsCollection.enumerateStatistics(from: startDate, to: endDate) { statistics, _ in
if let sum = statistics.sumQuantity() {
resultCount = Int(sum.doubleValue(for: .count()))
}
}
self?.logger.info("Got today's steps (initial): \(resultCount)")
finishWithResult(resultCount)
}
// subscribe for updates
query.statisticsUpdateHandler = { [weak self] _, statistics, _, error in
guard error == nil else { return }
if let sum = statistics?.sumQuantity() {
let steps = Int(sum.doubleValue(for: .count()))
self?.logger.info("Got today's steps (update): \(steps)")
finishWithResult(steps)
}
}
healthStore?.execute(query)
}
Got the same issue for quite some time. I have a guard statement before the query execution that ensures that the start date is before the end date and it still crashes for a small amount of users.