HealthKit
教學連結
Memo
- 三大重點:取得資料授權、讀、寫 - 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 write
let healthKitTypesToWrite: Set<HKSampleType> = [bodyMassIndex,
                                                activeEnergy,
                                                HKObjectType.workoutType()]
let healthKitTypesToRead: Set<HKObjectType> = [dateOfBirth,
                                               bloodType,
                                               biologicalSex,
                                               bodyMassIndex,
                                               height,
                                               bodyMass,
                                               HKObjectType.workoutType()]
//4. Request Authorization
HKHealthStore().requestAuthorization(toShare: healthKitTypesToWrite,
                                     read: healthKitTypesToRead) { (success, error) in
  completion(success, error)
}- 讀 
class func getMostRecentSample(for sampleType: 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 = 1
let 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 {
      guard let samples = samples,
            let mostRecentSample = samples.first as? HKQuantitySample else {
            completion(nil, error)
            return
      }
      completion(mostRecentSample, nil)
    }
  }
HKHealthStore().execute(sampleQuery)
}- 寫 
class func saveBodyMassIndexSample(bodyMassIndex: Double, date: Date) {
  //1.  Make sure the body mass type exists  
  guard let 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 quantity
  let bodyMassQuantity = HKQuantity(unit: HKUnit.count(),
                                    doubleValue: bodyMassIndex)
  let bodyMassIndexSample = HKQuantitySample(type: bodyMassIndexType,
                                             quantity: bodyMassQuantity,
                                             start: date,
                                             end: date)
  //3.  Save the same to HealthKit
  HKHealthStore().save(bodyMassIndexSample) { (success, error) in
    if let error = error {
      print("Error Saving BMI Sample: \(error.localizedDescription)")
    } else {
      print("Successfully saved BMI Sample")
    }
  }
}Tell if data was user entered manually
教學連結
- Ignore manual entries from Apple Health app as Data Source - [NSPredicate predicateWithFormat:@"metadata.%K != YES", HKMetadataKeyWasUserEntered];
- Detect if HealthKit activity has been entered manually - 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 
 
Memo
- 非手動輸入 
(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 : 1Create Multiple predicate
教學連結
- HealthKit: create a predicate for specific sources and date range - Use NSCompoundPredicate 
 
- //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])
獲取統計數據
教學連結
Memo
- 心率單位 - HKUnit(from: "count/min") or HKUnit.count().unitDivided(by: HKUnit.minute())
Last updated
Was this helpful?