【问题标题】:Using Combine's Publishers and Subscribers to publish real time HealthKit data?使用 Combine 的发布者和订阅者发布实时 HealthKit 数据?
【发布时间】:2020-07-21 18:01:05
【问题描述】:

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

我现在正在尝试使用 Combine 和 SwiftUI 来传递相同的数据,但我有点迷茫。我使用 WorkoutManager 类作为我在 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)
    }
}

【问题讨论】:

    标签: swift swiftui healthkit combine watchos


    【解决方案1】:

    //如何订阅更改?

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

    【讨论】:

    • 好吧,也许我在写轨道上,当我尝试这样做时`Text("($workoutManager.$totalEnergyBurned)")` 编译器说Cannot assign to property: '$totalEnergyBurned' is immutableInstance method 'appendInterpolation' requires that 'Binding<Published<Double>.Publisher>' conform to '_FormatSpecifiable'
    • 我不需要 $,让它与 Text("\(workoutManager.totalEnergyBurned)") 一起工作很容易 ?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-28
    相关资源
    最近更新 更多