SwiftUI:@State 变量永远不会从@Published 更新
SwiftUI: @State variable never get updated from @Published
我正在尝试在模型出现错误时触发警报,但它从未更新以显示警报:
这是我在视图中的实现:
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
@State var showAlert = false
init() {
viewModel = ViewModel()
showAlert = viewModel.showAlert
}
var body: some View {
NavigationView {
Text("Hello, world!")
.padding()
}
.alert(isPresented: $showAlert) {
Alert(title: Text("This works"),
message: Text("Hello"),
dismissButton: .default(Text("got it"))
)}
}
}
这是我的模型:
class ViewModel: ObservableObject {
@Published var showAlert = false
var cancellables = Set<AnyCancellable>()
init() {
DoSomething.shared.showAlert.sink { _ in
print("got new Value")
} receiveValue: {[weak self] value in
print("value")
self?.showAlert = value
}.store(in: &cancellables)
}
}
class DoSomething {
let showAlert = PassthroughSubject<Bool, Never>()
static let shared = DoSomething()
private init() {
checkToShowAlert()
}
func checkToShowAlert() {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) { [weak self] in
print("change value")
self?.showAlert.send(true)
}
}
}
你们中有人知道为什么 showAlert
变量永远不会更新吗?
非常感谢你的帮助
在您当前的代码中,您在 那个时间点将 ContentView
的 showAlert
设置为 ViewModel
的 showAlert
:
init() {
viewModel = ViewModel()
showAlert = viewModel.showAlert //<-- assignment at the time of init
}
意思是,赋值时是false
。因为它只是一个 Bool
被分配给另一个 Bool
,所以没有机制在 ViewModel
的 showAlert
发生变化时保持更新。
最简单的解决方案是摆脱您的 @State
变量并直接观察 @Published
属性:
struct ContentView: View {
@ObservedObject var viewModel: ViewModel = ViewModel()
var body: some View {
NavigationView {
Text("Hello, world!")
.padding()
}
.alert(isPresented: $viewModel.showAlert) {
Alert(title: Text("This works"),
message: Text("Hello"),
dismissButton: .default(Text("got it"))
)}
}
}
摆脱视图模型对象,这是主要问题。我们不在 SwiftUI 中使用它们。我们对视图数据使用 View 结构,并使用 @State
和 @Binding
属性 包装器使结构表现得像一个对象,因此您需要先了解它。
此外,我认为您不需要 Combine 来完成您想要做的事情,因为您没有使用 combineLatest
等组合任何东西,但是当我们在 SwiftUI 中使用它时,我们不使用 sink
或 store
,而不是我们 assign
管道的末端到 @Published
.
示例:
struct ContentView: View {
@State var isPresented = false
var body: some View {
NavigationView {
VStack{
Text("Hello, world!")
.padding()
Button("Show Alert") {
showAlert()
}
}
}
.alert(isPresented: $isPresented) {
Alert(title:Text("This works"),
message: Text("Hello"),
dismissButton: .default(Text("got it"))
)}
}
func showAlert() {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
isPresented = true
}
}
}
我正在尝试在模型出现错误时触发警报,但它从未更新以显示警报:
这是我在视图中的实现:
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
@State var showAlert = false
init() {
viewModel = ViewModel()
showAlert = viewModel.showAlert
}
var body: some View {
NavigationView {
Text("Hello, world!")
.padding()
}
.alert(isPresented: $showAlert) {
Alert(title: Text("This works"),
message: Text("Hello"),
dismissButton: .default(Text("got it"))
)}
}
}
这是我的模型:
class ViewModel: ObservableObject {
@Published var showAlert = false
var cancellables = Set<AnyCancellable>()
init() {
DoSomething.shared.showAlert.sink { _ in
print("got new Value")
} receiveValue: {[weak self] value in
print("value")
self?.showAlert = value
}.store(in: &cancellables)
}
}
class DoSomething {
let showAlert = PassthroughSubject<Bool, Never>()
static let shared = DoSomething()
private init() {
checkToShowAlert()
}
func checkToShowAlert() {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) { [weak self] in
print("change value")
self?.showAlert.send(true)
}
}
}
你们中有人知道为什么 showAlert
变量永远不会更新吗?
非常感谢你的帮助
在您当前的代码中,您在 那个时间点将 ContentView
的 showAlert
设置为 ViewModel
的 showAlert
:
init() {
viewModel = ViewModel()
showAlert = viewModel.showAlert //<-- assignment at the time of init
}
意思是,赋值时是false
。因为它只是一个 Bool
被分配给另一个 Bool
,所以没有机制在 ViewModel
的 showAlert
发生变化时保持更新。
最简单的解决方案是摆脱您的 @State
变量并直接观察 @Published
属性:
struct ContentView: View {
@ObservedObject var viewModel: ViewModel = ViewModel()
var body: some View {
NavigationView {
Text("Hello, world!")
.padding()
}
.alert(isPresented: $viewModel.showAlert) {
Alert(title: Text("This works"),
message: Text("Hello"),
dismissButton: .default(Text("got it"))
)}
}
}
摆脱视图模型对象,这是主要问题。我们不在 SwiftUI 中使用它们。我们对视图数据使用 View 结构,并使用 @State
和 @Binding
属性 包装器使结构表现得像一个对象,因此您需要先了解它。
此外,我认为您不需要 Combine 来完成您想要做的事情,因为您没有使用 combineLatest
等组合任何东西,但是当我们在 SwiftUI 中使用它时,我们不使用 sink
或 store
,而不是我们 assign
管道的末端到 @Published
.
示例:
struct ContentView: View {
@State var isPresented = false
var body: some View {
NavigationView {
VStack{
Text("Hello, world!")
.padding()
Button("Show Alert") {
showAlert()
}
}
}
.alert(isPresented: $isPresented) {
Alert(title:Text("This works"),
message: Text("Hello"),
dismissButton: .default(Text("got it"))
)}
}
func showAlert() {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
isPresented = true
}
}
}