如何解决此错误:“ Foundation._GenericObjCError错误0。”

时间:2019-05-15 17:35:50

标签: ios swift xcode health-kit hkhealthstore

我正在尝试构建一个从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")
            }
        }
    }
}

对错误消息的任何建议或解释将不胜感激!

3 个答案:

答案 0 :(得分:0)

您应该在您的应用程序中仅创建一个HKHealthStore实例,然后重用该实例。我不知道您的应用程序的结构,所以不知道最好的地方是保留对HKHealthStore的引用,但是AppDelegate始终是一个选择。

答案 1 :(得分:0)

不知道您是否仍然遇到此错误,但是我有同样的错误。我没有在模拟器的Health App中填写数据,因此当我尝试检索数据时,出现了错误。

我将数据填充到模拟器的Health App中,然后再次尝试,它就起作用了。

希望有帮助。

答案 2 :(得分:0)

检查您的帐户类型。 当我使用“企业”帐户时发生了同样的错误。 改成普通开发者账号后,发现运行正常。