HealthKit - 在 HKWorkoutSession 期间更改 HKWorkoutConfiguration?

Posted

技术标签:

【中文标题】HealthKit - 在 HKWorkoutSession 期间更改 HKWorkoutConfiguration?【英文标题】:HealthKit - Change HKWorkoutConfiguration during HKWorkoutSession? 【发布时间】:2021-04-07 05:34:48 【问题描述】:

我的问题如下:

我可以在使用期间更改HKWorkoutConfiguration.activityType HKWorkoutSession 或者每个HKWorkoutSession 都必须有自己的 HKWorkoutConfiguration.activityType?

我想创建一个锻炼应用程序,您可以在其中创建由具有不同活动类型的不同集合组成的锻炼。例如Shadowing Boxing Workout,包括3组拳击和3组跆拳道(拳击和跆拳道是不同的活动)。

理想情况下,我会在开始时启动一次HKWorkoutSession,并在完成每个活动的所有集合后结束它,并在中间更改HKWorkoutConfiguration.activityType

我目前的做法是基于苹果提供的样本:https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/speedysloth_creating_a_workout

我将startWorkout() 方法调整为startWorkout(for type: String)。现在看起来像这样:

// Start the workout.
    func startWorkout(for type: String) 
        // Start the timer.
        setUpTimer()
        self.running = true
        
        // Create the session and obtain the workout builder.
        /// - Tag: CreateWorkout
        do 
            session = try HKWorkoutSession(healthStore: healthStore, configuration: self.workoutConfiguration(for: type))
            
            builder = session.associatedWorkoutBuilder()
         catch 
            // Handle any exceptions.
            return
        
        
        // Setup session and builder.
        session.delegate = self
        builder.delegate = self
        
        // Set the workout builder's data source.
        /// - Tag: SetDataSource
        builder.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore,
                                                     workoutConfiguration: workoutConfiguration(for: type))
        
        // Start the workout session and begin data collection.
        /// - Tag: StartSession
        session.startActivity(with: Date())
        builder.beginCollection(withStart: Date())  (success, error) in
            // The workout has started.
        
        print("New Workout has started")
    

在方法中,我通过workoutConfiguration(for: type) 获取相应的活动,它从字符串中查找正确的活动。

完成一组训练(例如拳击组)后,我结束训练并开始新的锻炼和训练,并针对新的活动进行新训练。

我对当前方法的问题是我需要在开始新方法之前结束当前的HKWorkoutSession。但是以示例中的方式结束会话并不会立即执行,因此新的训练集开始时不会使用正确的活动将旧集保存到 HKStore。

因此,我认为只开始一次会话并在其间切换 activityTypes 会很好。但是,我不知道这是否可能(可能是 HKStore 的并发症)以及它是如何完成的。

或者有没有其他聪明的方法来实现这一点?

我刚刚开始接触 ios 编程。

非常感谢任何帮助!

【问题讨论】:

您无法更改健身课程的配置(因此也无法更改锻炼类型),您一次只能启用一个健身课程。 【参考方案1】:

免责声明:这不是一个完整的答案,而是我解决问题的方法。

查看workoutSession(_:didChangeTo:from:date:) 方法。 Documentation Link

当一种类型的锻炼结束时,该方法将收到通知。只要您没有致电session.end(),锻炼会话应该仍然处于活动状态。在开始新的锻炼之前,使用您的 healthStore 实例保存上一个锻炼会话。

它可能看起来像这样;

func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) 
    if toState == .ended 
        workoutBuilder.endCollection(withEnd: date)  (success, error) in
            // collection has ended for one type of workout
            self.workoutBuilder.finishWorkout  (workout, error) in
                // unwrap the optional `workout`
                guard let completedWorkout = workout else  return 
                // save workout to health store
                healthStore.save(completedWorkout)  (success, error) in
                    if success 
                        // begin a new workout by calling your method to start a new workout with a new configuration here
                        startWorkout(for type: String)
                    
                
            
        
    

这可能会导致您的计时器出现问题,因为您再次调用setUpTimer,但您可以使用它。此外,当用户完全完成锻炼并且不想开始新的锻炼类型时,这也没有解决这一点。

【讨论】:

谢谢,你让我走上了正确的道路。我没有在一组完成后结束每个会话,而是停止计时器并调用 builder.endcollection,重置锻炼,然后使用startworkout(for type: String) 开始新的一组。这样,我所有具有不同活动类型和时间的集合都可以正确记录在 healthstore 中。只有当所有的锻炼都完成后,我才结束了训练。显然,即使旧会话没有结束,也可以使用新的锻炼配置开始新会话。 好消息!我很高兴你能够完成它。

以上是关于HealthKit - 在 HKWorkoutSession 期间更改 HKWorkoutConfiguration?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 swift 3 中获取和更新 Healthkit 中的高度?

在我的应用程序中存储 HealthKit 数据

Meteor 中的 Healthkit 插件

Meteor 中的 Healthkit 插件

HealthKit框架

如何在您的应用中禁用 HealthKit 集成?