为啥我的 HKWorkoutSession(通常)没有结束?

Posted

技术标签:

【中文标题】为啥我的 HKWorkoutSession(通常)没有结束?【英文标题】:Why is my HKWorkoutSession (usually) not ending?为什么我的 HKWorkoutSession(通常)没有结束? 【发布时间】:2020-07-22 19:35:09 【问题描述】:

我正在为 Apple Watch 开发一个非常简单的锻炼应用程序。它使用 Health Kit 来开始和结束锻炼,我唯一的问题是当我尝试结束锻炼时它通常不会结束会话并且我收到此错误

2020-07-22 12:27:46.547720-0700 5k WatchKit Extension[25774:944527] [workouts] <HKWorkoutSession:0x80156310 A54AF52C-8B08-4BAD-A28C-03D8E54044B5 ended>: Failed to end: Error Domain=com.apple.healthkit Code=3 "Unable to transition to the desired state from the Ended(3) state (event 6). Allowed transitions from the current state are: 
    7 = "<error(7): Ended(3) -> Ended(3)>";
" UserInfo=NSLocalizedDescription=Unable to transition to the desired state from the Ended(3) state (event 6). Allowed transitions from the current state are: 
    7 = "<error(7): Ended(3) -> Ended(3)>";

我真的不知道从哪里开始从这些信息中寻找问题,我也不知道这意味着什么。此外,通常在第 4 次或第 5 次尝试时,它实际上会结束锻炼。

【问题讨论】:

【参考方案1】:

可能的原因是结束锻炼会话和锻炼构建器数据收集的错误顺序。

如果您的代码看起来与此类似,您将收到错误:

session.end()
        
builder.endCollection(withEnd: Date())  (success, error) in
 builder.finishWorkout  (workout, error) in
// do something
 

会话尚未结束,但代码会立即尝试结束构建器的会话。

在 Apple 的示例中 (https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/speedysloth_creating_a_workout) 是通过代表完成锻炼的正确方法:

session.delegate = self
.....
func endWorkout() 
        // End the workout session.
        session.end()

....
extension WorkoutManager: HKWorkoutSessionDelegate 
    func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState,
                        from fromState: HKWorkoutSessionState, date: Date) 
        // Wait for the session to transition states before ending the builder.
        /// - Tag: SaveWorkout
        if toState == .ended 
            print("The workout has now ended.")
            builder.endCollection(withEnd: Date())  (success, error) in
                self.builder.finishWorkout  (workout, error) in
                    // Optionally display a workout summary to the user.
                    self.resetWorkout()
                
            
        
    
    
    func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: Error) 
        
    

【讨论】:

【参考方案2】:

看起来您尝试结束会话两次(当它已经处于结束状态时)。

尝试在结束前检查当前状态。

if session.state == .running 
    session.stopActivity(with: Date())


if session.state == .stopped 
    session.end()

顺便说一句,根据我的经验,绿灯关闭可能需要一些时间(几秒钟)(您结束会话,手表上的绿灯会在几秒钟后关闭)

【讨论】:

谢谢,但这并不能完全结束锻炼。我很好奇您是如何阅读错误的,并且可以看到我正在尝试结束会话两次?我在阅读错误消息和调试它们方面很糟糕。【参考方案3】:

根据@Nastya 的回答,我还需要将session 设置为nil

session.delegate = self
.....
func endWorkout() 
        // End the workout session.
        session.end()

....
extension WorkoutManager: HKWorkoutSessionDelegate 
    func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState,
                        from fromState: HKWorkoutSessionState, date: Date) 
        // Wait for the session to transition states before ending the builder.
        /// - Tag: SaveWorkout
        if toState == .ended 
            print("The workout has now ended.")
            builder.endCollection(withEnd: Date())  (success, error) in
                self.builder.finishWorkout  (workout, error) in
                    // Optionally display a workout summary to the user.
                    self.resetWorkout()
                    
                    // I had to add this step
                    self.session = nil
                
            
        
    
    
    func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: Error) 
        
    

【讨论】:

以上是关于为啥我的 HKWorkoutSession(通常)没有结束?的主要内容,如果未能解决你的问题,请参考以下文章

HKWorkoutSession 不可用

如何使 HKworkoutsession 始终是一个积极的锻炼课程

如何使 HKworkoutsession 始终是一个积极的锻炼课程

无法使用 HKWorkoutSession 开始锻炼课程

HealthKit - 在 HKWorkoutSession 期间更改 HKWorkoutConfiguration?

HealthKit - 在 HKWorkoutSession 期间更改 HKWorkoutConfiguration?