鉴于我在下面概述的设置,我试图确定为什么ChildView
's.onChange(of: _)
没有收到更新。
import SwiftUI
struct SomeItem: Equatable {
var doubleValue: Double
}
struct ParentView: View {
@State
private var someItem = SomeItem(doubleValue: 45)
var body: some View {
Color.black
.overlay(alignment: .top) {
Text(someItem.doubleValue.description)
.font(.system(size: 50))
.foregroundColor(.white)
}
.onTapGesture { someItem.doubleValue += 10.0 }
.overlay { ChildView(someItem: $someItem) }
}
}
struct ChildView: View {
@StateObject
var viewModel: ViewModel
init(someItem: Binding<SomeItem>) {
_viewModel = StateObject(wrappedValue: ViewModel(someItem: someItem))
}
var body: some View {
Rectangle()
.fill(Color.red)
.frame(width: 50, height: 70, alignment: .center)
.rotationEffect(
Angle(degrees: viewModel.someItem.doubleValue)
)
.onTapGesture { viewModel.changeItem() }
.onChange(of: viewModel.someItem) { _ in
print("Change Detected", viewModel.someItem.doubleValue)
}
}
}
@MainActor
final class ViewModel: ObservableObject {
@Binding
var someItem: SomeItem
public init(someItem: Binding<SomeItem>) {
self._someItem = someItem
}
public func changeItem() {
self.someItem = SomeItem(doubleValue: .zero)
}
}
有趣的是,如果我在 中进行以下更改ChildView
,我会得到我想要的行为。
更改
@StateObject
为@ObservedObject
更改
_viewModel = StateObject(wrappedValue: ViewModel(someItem: someItem))
为viewModel = ViewModel(someItem: someItem)
据我了解,ChildView
's是不合适的viewModel
,@ObservedObject
因为ChildView
拥有viewModel
但@ObservedObject
给了我我需要的行为,而@StateObject
没有。
以下是我要注意的差异:
- 使用 时
@ObservedObject
,我可以点击黑色区域并查看应用于白色文本和红色矩形的更改。ParentView
我还可以点击红色矩形并通过白色文本查看观察到的变化。 - 使用 时
@StateObject
,我可以点击黑色区域并查看应用于白色文本和红色矩形的更改。问题在于我可以点击此处的红色矩形并查看反映的更改ParentView
但ChildView
无法识别更改(旋转不更改并且未打印“检测到更改”)。
实际上是@ObservedObject
正确的,因为ViewModel
包含 a@Binding
到 a @State
created inParentView
吗?