2

我正在尝试制作一个锻炼应用程序,其中用户的心率显示在 Apple Watch 上。我一直在关注 Apple 的 WWDC“锻炼的新方法”视频。这是链接https://developer.apple.com/videos/play/wwdc2018/707/?time=615

无论如何,每次我尝试运行应用程序时,我都会收到错误消息“线程 1:在展开可选值时意外发现致命错误”

 session = try HKWorkoutSession(healthStore: healthStore, configuration: configuration)

我尝试在“尝试”之后添加一个问号(?),但所做的只是防止应用程序崩溃并且不会开始锻炼。这是完整的代码。PS 我对 Swift 还很陌生,我发现新的 HealthKit 还没有太多示例代码,这让我非常沮丧。(我知道它相当新,但仍然令人沮丧:D)。谢谢您的帮助

class InterfaceController: WKInterfaceController, HKWorkoutSessionDelegate, HKLiveWorkoutBuilderDelegate {

    let healthStore = HKHealthStore()
    var configuration: HKWorkoutConfiguration!

    var session: HKWorkoutSession!
    var builder: HKLiveWorkoutBuilder!


func startWorkoutWithHealthStore(){

      //  configuration.activityType = .crossTraining
    //    configuration.locationType = .indoor

        do {
            session = try? HKWorkoutSession(healthStore: healthStore, configuration: configuration)
        } catch {
            // let the user know about the error
            return
        }

        builder = session.associatedWorkoutBuilder()


        //Setup session and builder

        session.delegate = self
        builder.delegate = self

        builder.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: configuration)


                //Start Session & Builder

        session.startActivity(with: Date())


        builder.beginCollection(withStart: Date()) { (success, error) in
            self.setDurationTimerDate() //Start the elapsed time timer
        }

    }

    @IBAction func startButtonClicked() {

        print("Start BTN clicked")
        startWorkoutWithHealthStore()

    }

    //Track Elapsed Time
    func workoutBuilderDidCollectEvent(_ workoutBuilder: HKLiveWorkoutBuilder){

        print("Collection Started")
        setDurationTimerDate()

    }

    func setDurationTimerDate(){
        print(", duration timer started"
        )
        //Create WKInterfaceTimer Date
        let timerDate = Date(timeInterval: -self.builder.elapsedTime, since: Date())
        DispatchQueue.main.async {
            self.timer.setDate(timerDate)
        }
        //Start or stop timer
        let sessionState = self.session.state
        DispatchQueue.main.async {
            sessionState == .running ? self.timer.start() : self.timer.stop()
        }
    }

    // MARK: HKLiveWorkoutBuilderDelegate
    func workoutBuilder(_ workoutBuilder: HKLiveWorkoutBuilder, didCollectDataOf collectedTypes: Set<HKSampleType>){

        for type in collectedTypes{

            guard let quantityType = type as? HKQuantityType else {
                return // Do nothing
            }


            let statistics = workoutBuilder.statistics(for: quantityType)
            //let label = labelForQuantityType(quantityType)

           // updateLabel(wkLabel, withStatistics: statistics)

            print(statistics as Any)
        }


    }

    // MARK: State Control
    func stopWorkout(){

        session.end()
        builder.endCollection(withEnd: Date()) { (success, error) in

            self.builder.finishWorkout(completion: { (workout, error) in
                self.dismiss()
            })

        }
    }


}
4

1 回答 1

2

Optional您不应该使用try?throw by将错误屏蔽为 an HKWorkoutSession(healthStore: healthStore, configuration: configuration),尤其是如果您已经将该语句放在一个do-catch块中。你会崩溃,因为session它被定义为一个隐式展开的可选(!类型后面的标记),它不应该是。

session如果它可能具有nil值并在每次访问它时安全地解开/可选链,则应将其定义为普通可选。

class InterfaceController: WKInterfaceController, HKWorkoutSessionDelegate, HKLiveWorkoutBuilderDelegate {

    let healthStore = HKHealthStore()
    let configuration = HKWorkoutConfiguration()

    var session: HKWorkoutSession? = nil
    var builder: HKLiveWorkoutBuilder? = nil


    func startWorkoutWithHealthStore(){
        configuration.activityType = .crossTraining
        configuration.locationType = .indoor

        do {
            session = try HKWorkoutSession(healthStore: healthStore, configuration: configuration)
        } catch {
            print(error)
            session = nil
            return
        }

        builder = session?.associatedWorkoutBuilder()


        //Setup session and builder

        session?.delegate = self
        builder?.delegate = self

        builder?.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: configuration)


        //Start Session & Builder
        session?.startActivity(with: Date())


        builder?.beginCollection(withStart: Date()) { (success, error) in
            self.setDurationTimerDate() //Start the elapsed time timer
        }

    }
...
}
于 2018-11-06T11:54:17.763 回答