使用 Combine 的发布者和订阅者发布实时 HealthKit 数据?

Using Combine's Publishers and Subscribers to publish real time HealthKit data?

我一直在 UIKit 和 WatchKit 中使用委托来在对象之间进行通信,例如传递数据。一个 WorkoutManager ViewModel,它在 HKworkout 期间接收来自 HealthKit 的委托回调,将卡路里、心率传递给 InterfaceController。

我现在正在尝试使用 Combine 和 SwiftUI 来传递相同的数据,但我有点不知所措。我使用 WorkoutManager class 作为我在 ContentView 中初始化的环境对象:

class WorkoutManager: NSObject, HKWorkoutSessionDelegate, HKLiveWorkoutBuilderDelegate, ObservableObject  {

    @Published var totalEnergyBurned: Double = 0

    //How to subscribe to the changes? 

//Omitted HealthKit code that queries and pushes data into totalEnergyBurned here

}



struct ContentView: View {
    
    let healthStore = HKHealthStore()
    @StateObject var workoutManager = WorkoutManager()
    
    var sessionTypes = [SessionType.Game, SessionType.Practice, SessionType.Pickup]
    
    var body: some View {
        
        List {
            ForEach(sessionTypes) { sessionType  in
                NavigationLink(destination: LiveWorkoutView(sessionType: sessionType)) {
                    SessionTypeRow(name: sessionType.stringValue)
                }
            }
        }
        .navigationTitle("Let's Go!")
        .onAppear {
            let authorizationStatus = healthStore.authorizationStatus(for: HKSampleType.workoutType())
            switch authorizationStatus {
            case .sharingAuthorized:
                print("sharing authorized")
            case .notDetermined:
                print("not determined")
                HealthKitAuthManager.authorizeHealthKit()
            case .sharingDenied:
                print("sharing denied")
                HealthKitAuthManager.authorizeHealthKit()
            default:
                print("default in healthStore.authorizationStatus in ContentView")
                HealthKitAuthManager.authorizeHealthKit()
            }
        }
    }
}

我的目标是将更改发布到 ContentView 的所有子项,但我不确定如何订阅更改?

import SwiftUI

struct LiveWorkoutView: View {

@State var sessionType: SessionType
    
    @StateObject var workoutManager = WorkoutManager()
    
    var body: some View {
        VStack {
            Text("\(workoutManager.totalEnergyBurned)")
            Button(action: {
                workoutManager.stopWorkout()
            }) {
                Text("End Workout")
            }
        }
        .onAppear {
            workoutManager.startWorkout()
            workoutManager.sessionType = sessionType
        }
        .navigationTitle(sessionType.stringValue)
    }
}

//How to subscribe to the changes?

你不知道。 @StateObject 在视图中注入订阅者,因此只需在视图 body 中的某处(需要的地方)使用 workoutManager. totalEnergyBurned 属性 并且一旦此 属性 更改,视图将自动刷新(例如,您从 HealthKit 回调中为其分配新值。