我正在尝试构建一个从Apple Health App读取数据的应用程序。
我的应用程序请求用户允许从HealthKit访问数据。授予应用程序权限后尝试读取数据时,出现以下错误消息:
该操作无法完成。 (Foundation._GenericObjCError错误0。)
Xcode上没有错误显示;该消息仅在设备上测试时出现。
这是代码中获得HealthKit许可的部分:
import Foundation
import HealthKit
class HealthKitSetupAssistant{
private enum HealthkitSetupError: Error{
case notAvailableOnDevice
case dataTypeNotAvailable
}
class func authorizeHealthKit(completion: @escaping (Bool, Error?) -> Swift.Void){
// 1. Check to see if HealthKit is available on this device
guard HKHealthStore.isHealthDataAvailable() else{
completion(false, HealthkitSetupError.notAvailableOnDevice)
return
}
//2. Prepare the data types that will interact with HealthKit
guard let dateOfBirth = HKObjectType.characteristicType(forIdentifier: .dateOfBirth),
let bloodType = HKObjectType.characteristicType(forIdentifier: .bloodType),
let biologicalSex = HKObjectType.characteristicType(forIdentifier: .biologicalSex),
let bodyMassIndex = HKObjectType.quantityType(forIdentifier: .bodyMassIndex),
let height = HKObjectType.quantityType(forIdentifier: .height),
let bodyMass = HKObjectType.quantityType(forIdentifier: .bodyMass),
let activeEnergy = HKObjectType.quantityType(forIdentifier: .activeEnergyBurned) else{
completion(false, HealthkitSetupError.dataTypeNotAvailable)
return
}
//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)
}
}
}
这是代码中尝试从HealthKit读取数据的部分:
import Foundation
import HealthKit
class ProfileDataStore {
class func getAgeSexAndBloodType() throws -> (age: Int,
biologicalSex: HKBiologicalSex,
bloodType: HKBloodType) {
let healthKitStore = HKHealthStore()
do {
//1. This method throws an error if these data are not available.
let birthdayComponents = try healthKitStore.dateOfBirthComponents()
let biologicalSex = try healthKitStore.biologicalSex()
let bloodType = try healthKitStore.bloodType()
//2. Use Calendar to calculate age.
let today = Date()
let calendar = Calendar.current
let todayDateComponents = calendar.dateComponents([.year],
from: today)
let thisYear = todayDateComponents.year!
let age = thisYear - birthdayComponents.year!
//3. Unwrap the wrappers to get the underlying enum values.
let unwrappedBiologicalSex = biologicalSex.biologicalSex
let unwrappedBloodType = bloodType.bloodType
return (age, unwrappedBiologicalSex, unwrappedBloodType)
}
}
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")
}
}
}
}
对错误消息的任何建议或解释将不胜感激!
答案 0 :(得分:0)
您应该在您的应用程序中仅创建一个HKHealthStore实例,然后重用该实例。我不知道您的应用程序的结构,所以不知道最好的地方是保留对HKHealthStore的引用,但是AppDelegate始终是一个选择。
答案 1 :(得分:0)
不知道您是否仍然遇到此错误,但是我有同样的错误。我没有在模拟器的Health App中填写数据,因此当我尝试检索数据时,出现了错误。
我将数据填充到模拟器的Health App中,然后再次尝试,它就起作用了。
希望有帮助。
答案 2 :(得分:0)
检查您的帐户类型。 当我使用“企业”帐户时发生了同样的错误。 改成普通开发者账号后,发现运行正常。