检查Apple Watch是否已授予HealthKit权限的最佳方法?

时间:2018-03-07 17:51:07

标签: ios swift apple-watch health-kit

我知道HealthKit仍然要求用户通过iPhone授权HealthKit权限,即使对于Watch应用程序也是如此。事实上,Apple自己的Sample Code手表上没有任何授权码。如果您在手表上打开Speedy Sloth而不打开iPhone(要求访问),该应用程序将不会开始锻炼(因为它未经授权)而没有通知。

话虽如此,我们观察开发者必须按照我的理解在Watch上实施我们自己的授权检查并弹出警报以提醒用户打开iPhone应用程序并在未经授权时进行授权。

下面的代码是我对此的实现,但是用户偶尔会报告有授权问题,例如连续启动多个锻炼时。任何人都可以在我的逻辑中看到任何缺陷吗?

import WatchKit
import Foundation
import HealthKit


class InterfaceController: WKInterfaceController {

    // MARK: - Properties

    private let healthStore = HKHealthStore()
    private var healthKitAuthorized = false

    // MARK: - Interface Controller Overrides

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

    }

    override func willActivate() {
        super.willActivate()

        requestAccessToHealthKit()

    }


    @IBAction func didTapStartButton() {
     segueToWorkOutInterfaceControllerIfAuthorized()
    }

    private func requestAccessToHealthKit() {
        let healthStore = HKHealthStore()

        let healthKitTypesToWrite: Set<HKSampleType> = [
            HKObjectType.workoutType(),
            HKSeriesType.workoutRoute(),
            HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
            HKObjectType.quantityType(forIdentifier: .heartRate)!,
            HKObjectType.quantityType(forIdentifier: .restingHeartRate)!,
            HKObjectType.quantityType(forIdentifier: .bodyMass)!,
            HKObjectType.quantityType(forIdentifier: .vo2Max)!,
            HKObjectType.quantityType(forIdentifier: .stepCount)!,
            HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!]

        let healthKitTypesToRead: Set<HKObjectType> = [
            HKObjectType.workoutType(),
            HKSeriesType.workoutRoute(),
            HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
            HKObjectType.quantityType(forIdentifier: .heartRate)!,
            HKObjectType.quantityType(forIdentifier: .restingHeartRate)!,
            HKObjectType.characteristicType(forIdentifier: .dateOfBirth)!,
            HKObjectType.quantityType(forIdentifier: .bodyMass)!,
            HKObjectType.quantityType(forIdentifier: .vo2Max)!,
            HKObjectType.quantityType(forIdentifier: .stepCount)!,
            HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!]


        healthStore.requestAuthorization(toShare: healthKitTypesToWrite, read: healthKitTypesToRead) { (success, error) in

            if let unwrappedError = error {
                DispatchQueue.main.async {

                    print("Watch Healthkit Authorization Error = \(unwrappedError.localizedDescription)")
                    WKInterfaceDevice.current().play(.notification)
                    self.showAlertWith(title: "HealthKit Permission Needed", message: "Open the App on your iPhone or go to -> Settings -> Privacy -> Health -> App and turn on permissions")
                }
            }

            if !success {
                DispatchQueue.main.async {
                    print("Watch Healthkit Authorization was unsuccessful no error reported")
                    WKInterfaceDevice.current().play(.notification)
                    self.showAlertWith(title: "HealthKit Permission Needed", message: "Open the App on your iPhone or go to -> Settings -> Privacy -> Health -> App and turn on permissions")
                }
            }
            DispatchQueue.main.async {
                self.healthKitAuthorized = true
                print("Successful HealthKit Authorization FROM INTERFACE CONTROLLER")
            }
        }
    }
    func showAlertWith(title: String, message: String){

        let action1 = WKAlertAction(title: "OK", style: .default) {
            WKInterfaceController.reloadRootPageControllers(withNames: ["InterfaceController"],
                                                            contexts: nil,
                                                            orientation: .vertical,
                                                            pageIndex: 0)

        }
        presentAlert(withTitle: title, message: message, preferredStyle: .alert, actions: [action1])
    }


    func segueToWorkOutInterfaceControllerIfAuthorized() {
        if healthKitAuthorized {


            WKInterfaceController.reloadRootPageControllers(withNames: ["WorkoutInterfaceController"],
                                                            contexts: [contextDictionary],
                                                            orientation: .vertical,
                                                            pageIndex: 0)
        } else {
            self.showAlertWith(title: "HealthKit Permission Needed", message: "Open your iPhone -> Settings -> Privacy -> Health -> App  and turn on permissions")
        }
    }

}

1 个答案:

答案 0 :(得分:0)

我决定将我的HealthKit授权流程放入我的应用程序ExtensionDelegate而不是InterfaceController,并且到目前为止测试似乎更可靠地工作/触发,显然更多鉴于我不需要授权,除非需要,否则我的原始代码发布效率很高。仍然会欣赏其他人对此的任何意见。

import WatchKit
import HealthKit
import WatchConnectivity


class ExtensionDelegate: NSObject, WKExtensionDelegate, WCSessionDelegate {

    let healthStore = HKHealthStore()
    var watchSession: WCSession?
    let defaults = UserDefaults.standard

    func applicationDidFinishLaunching() {

        requestAccessToHealthKit()

    }

   private func requestAccessToHealthKit() {


        let healthKitTypesToWrite: Set<HKSampleType> = [
            HKObjectType.workoutType(),
            HKSeriesType.workoutRoute(),
            HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
            HKObjectType.quantityType(forIdentifier: .heartRate)!,
            HKObjectType.quantityType(forIdentifier: .restingHeartRate)!,
            HKObjectType.quantityType(forIdentifier: .bodyMass)!,
            HKObjectType.quantityType(forIdentifier: .vo2Max)!,
            HKObjectType.quantityType(forIdentifier: .stepCount)!,
            HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!]

        let healthKitTypesToRead: Set<HKObjectType> = [
            HKObjectType.workoutType(),
            HKSeriesType.workoutRoute(),
            HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
            HKObjectType.quantityType(forIdentifier: .heartRate)!,
            HKObjectType.quantityType(forIdentifier: .restingHeartRate)!,
            HKObjectType.characteristicType(forIdentifier: .dateOfBirth)!,
            HKObjectType.quantityType(forIdentifier: .bodyMass)!,
            HKObjectType.quantityType(forIdentifier: .vo2Max)!,
            HKObjectType.quantityType(forIdentifier: .stepCount)!,
            HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!]

        let authorizationStatus = healthStore.authorizationStatus(for: HKSampleType.workoutType())

        switch authorizationStatus {

            case .sharingAuthorized: print("sharing authorized")
                print("sharing authorized this message is from Watch's extension delegate")

            case .sharingDenied: print("sharing denied")

               healthStore.requestAuthorization(toShare: healthKitTypesToWrite, read: healthKitTypesToRead) { (success, error) in
                    print("Successful HealthKit Authorization from Watch's extension Delegate")
            }

            default: print("not determined")

            healthStore.requestAuthorization(toShare: healthKitTypesToWrite, read: healthKitTypesToRead) { (success, error) in
                print("Successful HealthKit Authorization from Watch's extension Delegate")
            }

        }
    }
}

然后在InterfaceController

 @IBAction func didTapStartButton() {

        let authorizationStatus = healthStore.authorizationStatus(for: HKSampleType.workoutType())

        switch authorizationStatus {
        case .sharingAuthorized: print("sharing authorized")
             segueToWorkoutInterfaceControllerWithContext()

        case .sharingDenied: print("sharing denied")
            self.showAlertWith(title: "HealthKit Permission Denied", message: "Please open The App on your iPhone or go to -> Settings -> Privacy -> Health -> App and turn on all permissions")

        default: print("not determined")
            self.showAlertWith(title: "HealthKit Permission Not Determined", message: "Please open The App on your iPhone or go to -> Settings -> Privacy -> Health -> App and turn on all permissions")
        }

    }