使用 Combine 的发布者和订阅者发布实时 HealthKit 数据?
Posted
技术标签:
【中文标题】使用 Combine 的发布者和订阅者发布实时 HealthKit 数据?【英文标题】:Using Combine's Publishers and Subscribers to publish real time HealthKit data? 【发布时间】: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)
【问题讨论】:
【参考方案1】://如何订阅更改?
你没有。 @StateObject
在视图中注入订阅者,因此只需在视图 body
中的某处(需要时)使用 workoutManager. totalEnergyBurned
属性,一旦此属性更改,视图将自动刷新(例如,您从 HealthKit 回调中为其分配新值。
【讨论】:
好吧,也许我在写轨道上,当我尝试这样做时`Text("($workoutManager.$totalEnergyBurned)")` 编译器说Cannot assign to property: '$totalEnergyBurned' is immutable
和Instance method 'appendInterpolation' requires that 'Binding<Published<Double>.Publisher>' conform to '_FormatSpecifiable'
我不需要 $,让它与 Text("\(workoutManager.totalEnergyBurned)")
一起工作很容易 ?以上是关于使用 Combine 的发布者和订阅者发布实时 HealthKit 数据?的主要内容,如果未能解决你的问题,请参考以下文章
Combine - 测试 CurrentValueSubject 是不是有订阅者
谈谈Combine中一个有趣操作符flatMap的使用与陷阱
谈谈Combine中一个有趣操作符flatMap的使用与陷阱