How to request permission and access HealthKit data
How to read HealthKit data
How to write data to HealthKit’s central repository
授權
//3. Prepare a list of types you want HealthKit to read and writelet healthKitTypesToWrite: Set<HKSampleType>= [bodyMassIndex, activeEnergy, HKObjectType.workoutType()]let healthKitTypesToRead: Set<HKObjectType>= [dateOfBirth, bloodType, biologicalSex, bodyMassIndex, height, bodyMass, HKObjectType.workoutType()]//4. Request AuthorizationHKHealthStore().requestAuthorization(toShare: healthKitTypesToWrite, read: healthKitTypesToRead) { (success, error) incompletion(success, error)}
讀
classfuncgetMostRecentSample(forsampleType: HKSampleType,completion: @escaping (HKQuantitySample?, Error?) -> Swift.Void) {//1. Use HKQuery to load the most recent samples. let mostRecentPredicate = HKQuery.predicateForSamples(withStart: Date.distantPast, end: Date(), options: .strictEndDate)let sortDescriptor =NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending:false)let limit =1let sampleQuery =HKSampleQuery(sampleType: sampleType, predicate: mostRecentPredicate, limit: limit, sortDescriptors: [sortDescriptor]) { (query, samples, error) in//2. Always dispatch to the main thread when complete. DispatchQueue.main.async {guardlet samples = samples,let mostRecentSample = samples.firstas? HKQuantitySample else {completion(nil, error)return }completion(mostRecentSample, nil) } }HKHealthStore().execute(sampleQuery)}
寫
classfuncsaveBodyMassIndexSample(bodyMassIndex: Double, date: Date) {//1. Make sure the body mass type exists guardlet bodyMassIndexType = HKQuantityType.quantityType(forIdentifier: .bodyMassIndex)else {fatalError("Body Mass Index Type is no longer available in HealthKit") }//2. Use the Count HKUnit to create a body mass quantitylet bodyMassQuantity =HKQuantity(unit: HKUnit.count(), doubleValue: bodyMassIndex)let bodyMassIndexSample =HKQuantitySample(type: bodyMassIndexType, quantity: bodyMassQuantity, start: date, end: date)//3. Save the same to HealthKitHKHealthStore().save(bodyMassIndexSample) { (success, error) iniflet error = error {print("Error Saving BMI Sample: \(error.localizedDescription)") } else {print("Successfully saved BMI Sample") } }}
The bundle identifier of the entry if made manually will be com.apple.Health, which is the bundle identifier of the Health app. Notice the capital H. When you pull your data just ignore the data which has a bundle identifier of com.apple.Health.
That way you will be only considering activities which are not manual
(lldb) po samples[1].source.bundleIdentifier
"com.apple.health.6AE18D38-5413-4679-BDBA-7FBD1DA9A45C"
(lldb) po samples[1].source.name
"電商科的iPhoneX"
(lldb) po samples[1].metadata
nil
手動輸入
(lldb) po samples[2].source.bundleIdentifier
"com.apple.Health"
(lldb) po samples[2].source.name
"健康"
(lldb) po samples[2].metadata
▿ Optional<Dictionary<String, Any>>
▿ some : 1 element
▿ 0 : 2 elements
- key : "HKWasUserEntered"
- value : 1
//1. Get all workouts with the "Other" activity type.
let workoutPredicate = HKQuery.predicateForWorkouts(with: .other)
//2. Get all workouts that only came from this app.
let sourcePredicate = HKQuery.predicateForObjects(from: HKSource.default())
//3. Combine the predicates into a single predicate.
let compound = NSCompoundPredicate(andPredicateWithSubpredicates: [workoutPredicate,
sourcePredicate])