[英]SwiftUI - changes in nested View Model classes not detected using onChange method
我有一个嵌套视图 Model class WatchDayProgramViewModel
作为 ObservableObject。 在WatchDayProgramViewModel
中,有一个WorkoutModel
是一个孩子 class。我想检测currentHeartRate
中的任何更新以触发数据传输到 iPhone。
因此,我尝试从 ContentView 使用WatchDayProgramViewModel
作为EnvironmentObject
并通过onChange()
方法检测WorkoutModel
中的变化。 但似乎 SwiftUI 视图没有检测到WorkoutModel
中的任何属性更改。
我知道这个问题可能是由于 ObservableObject 没有检测到子类/嵌套级别的变化,所以答案( SwiftUI 多级子级的变化发布 object 变化)建议使用struct
而不是 class。但是将WorkoutModel
更改为struct
导致各种@Published
已@Published
的属性和函数以显示错误。
是否有任何可能的方法从ContentView
本身检测子视图 Model 的变化?
内容视图
struct ContentView: View {
@State var selectedTab = 0
@StateObject var watchDayProgramVM = WatchDayProgramViewModel()
var body: some View {
NavigationView {
TabView(selection: $selectedTab) {
WatchControlView().id(0)
NowPlayingView().id(1)
}
.environmentObject(watchDayProgramVM)
.onChange(of: self.watchDayProgramVM.workoutModel.currentHeartRate) { newValue in
print("WatchConnectivity heart rate from contentView \(newValue)")
}
}
}
WatchDayProgramViewModel
class WatchDayProgramViewModel: ObservableObject {
@Published var workoutModel = WorkoutModel()
init() {
}
}
锻炼模式
import Foundation
import HealthKit
class WorkoutModel: NSObject, ObservableObject {
let healthStore = HKHealthStore()
var session: HKWorkoutSession?
var builder: HKLiveWorkoutBuilder?
@Published var currentHeartRate: Double = 0
@Published var workout: HKWorkout?
//Other functions to start/run workout hidden
func updateForStatistics(_ statistics: HKStatistics?) {
guard let statistics = statistics else {
return
}
DispatchQueue.main.async {
switch statistics.quantityType {
case HKQuantityType.quantityType(forIdentifier: .heartRate):
let heartRateUnit = HKUnit.count().unitDivided(by: HKUnit.minute())
self.currentHeartRate = statistics.mostRecentQuantity()?.doubleValue(for: heartRateUnit) ?? 0
default:
return
}
}//end of dispatchqueue
}// end of function
}
extension WorkoutModel: HKLiveWorkoutBuilderDelegate {
func workoutBuilder(_ workoutBuilder: HKLiveWorkoutBuilder, didCollectDataOf collectedTypes: Set<HKSampleType>) {
for type in collectedTypes {
guard let quantityType = type as? HKQuantityType else {
return
}
let statistics = workoutBuilder.statistics(for: quantityType)
updateForStatistics(statistics)
}
}
}
尝试改变
@StateObject var watchDayProgramVM = WatchDayProgramViewModel()
和
@ObservedObject var watchDayProgramVM = WatchDayProgramViewModel()
想办法。 只需创建另一个AnyCancellable
变量来调用objectWillChange
发布者。
WatchDayProgramViewModel
class WatchDayProgramViewModel: ObservableObject {
@Published var workoutModel = WorkoutModel()
var cancellable: AnyCancellable?
init() {
cancellable = workoutModel.objectWillChange
.sink { _ in
self.objectWillChange.send()
}
}
}
虽然我已经提供了我的答案,但我很乐意看到/获得有关其他替代方案的建议。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.