getEarliestAuthorizedSampleDate(for:completion:)
Returns the earliest date that the person permits your app to read samples for the given data types.
Declaration
func getEarliestAuthorizedSampleDate(for types: Set<HKObjectType>, completion: @escaping @Sendable ([HKObjectType : Date]?, (any Error)?) -> Void)Parameters
- types:
The set of Hkobjecttype values to query. HealthKit omits any type that doesn’t have a limited-access earliest date from the result.
- completion:
A closure with a dictionary parameter that maps qualifying types to their earliest readable date, or an error on failure.
Mentioned in
Discussion
This method derives the earliest sample date from availability in the HealthKit store as well as from the time frame a person chooses in the authorization prompt.
Call this method after requesting authorization to determine whether the person restricts your app’s read access to a time window as opposed to the full available history. Adjust your app’s workflow to work with less data. In particular, if the person limits your app’s access, ensure that any trends, baselines, or anomaly detections your app offers work from partial data.
When someone grants limited access to a data type, this method returns the earliest date from which your app can read samples of that type. Treat all data before that date as unknown — not an absence of data — because a full history may exist outside the range your app is permitted to read.
If your app has full access to a type, or if the person denies access, this method returns no entry for that type in the resulting dictionary. Your app can’t distinguish between denied and full access; limited authorization is the only state your app can identify, by design. The dictionary that this method produces is empty if no type has limited access. HealthKit omits a type from the result when:
Your app doesn’t have read access for the type.
Your app has full read access to the type.
Your app has limited read access but no specific earliest readable date is available.
To distinguish between a type that you request but has no time boundary and a type that isn’t part of your request at all, compare the returned dictionary’s keys against your input set. A type that appears in your input set but not in the result either has full access or no access; the framework doesn’t silently skip a type.
If your app makes inferences on partial data, consider informing people that granting full access improves your app’s experience.
Adjust queries for limited authorization
If your app queries HealthKit data by date range, consider incorporating the returned dates into your query predicate. If your app uses HKAnchoredObjectQuery with a saved anchor, the anchor automatically scopes the query to changes since the last fetch.
For each type your app queries, compare your intended query start date and the authorization date for that type and use whichever is later. This ensures that the query requests just the data your app needs. Varying types can have a different earliest date, so calculate the date per type, as shown here:
let types: Set<HKObjectType> = [HKQuantityType(.stepCount)]
let authorizationDates = try await store.earliestAuthorizedSampleDate(for: types)
let intendedStartDate = Date().addingTimeInterval(-90 * 24 * 3600)
let authorizationDate = authorizationDates[HKQuantityType(.stepCount)]
let queryStartDate = [intendedStartDate, authorizationDate]
.compactMap { $0 }
.max() ?? intendedStartDate
let predicate = HKQuery.predicateForSamples(
withStart: queryStartDate,
end: .now,
options: .strictStartDate
)See Also
Accessing HealthKit
authorizationStatus(for:)HKAuthorizationStatusgetRequestStatusForAuthorization(toShare:read:completion:)HKAuthorizationRequestStatusisHealthDataAvailable()supportsHealthRecords()requestAuthorization(toShare:read:completion:)requestAuthorization(toShare:read:)requestPerObjectReadAuthorization(for:predicate:completion:)handleAuthorizationForExtension(completion:)authorizationViewControllerPresenterearliestPermittedSampleDate()