发布值更改后不会触发 onReceive
Posted
技术标签:
【中文标题】发布值更改后不会触发 onReceive【英文标题】:onReceive is not triggered after published value has changed 【发布时间】:2021-02-21 20:22:33 【问题描述】:关键是在成功将记录添加到数据库后(当我点击确认按钮时),应该关闭视图。问题是添加后没有关闭,.onReceive
没有触发,虽然发布者PassthroughSubject
发送了一个新值。有一件事:如果在单击确认按钮之前触发了警报,则视图将关闭(例如,当未填写所有字段时,将显示警告)
此外,属性viewModel.name
和viewModel.name
(对于TextField
's)在添加记录后变为等于空字符串,尽管我没有在代码中的任何地方明确地为它们分配这样的值(就像一个新的视图模型的实例是在这些默认值所在的位置创建的)
查看:
struct AddChallengeView: View
@Environment(\.presentationMode) var presentationMode
@ObservedObject var viewModel = AddChallengeViewModel()
var body: some View
Form
Section(header: Text("Name"))
TextField("Type challenge name", text: $viewModel.name) //viewModel.name == "" after new record added
Section(header: Text("Description"))
TextEditor(text: $viewModel.description) //viewModel.description == "" after new record added
//...
Section
Button(action: viewModel.addChallenge())
HStack
Spacer()
Text("Submit").bold()
Spacer()
.alert(isPresented: $viewModel.showErrorAlert)
Alert(title: Text("Please, set all values!"))
.onReceive(viewModel.viewDismissalModePublisher) shouldDismiss in
print("new value received") //not printed
if shouldDismiss
self.presentationMode.wrappedValue.dismiss()
视图模型:
class AddChallengeViewModel: ObservableObject
var viewDismissalModePublisher = PassthroughSubject<Bool, Never>()
private var shouldDismissView = false
print("sending new value") //printed
didSet
viewDismissalModePublisher.send(shouldDismissView)
@Published var showErrorAlert = false
@Published var name = ""
@Published var description = ""
//...
func addChallenge ()
//...
if (name != "" && description != "" && grounds.count != 0)
Firestore.firestore().collection("users").document(Auth.auth().currentUser!.uid).collection("challenges").addDocument(data: [
"name": "\(name)",
"description": "\(description)",
"grounds": grounds
]) err in
if let err = err
print("Error adding document: \(err)")
else
print("setting new value") //printed
self.shouldDismissView = true
else
showErrorAlert.toggle()
更新:我找到了解决方案。我们需要将AddChallengeView
中的@StateObject var viewModel = AddChallengeViewModel()
替换为@ObservedObject var viewModel = AddChallengeViewModel()
,但为什么它会起作用?
【问题讨论】:
【参考方案1】:但为什么它会起作用?
您很可能在NavigationView
中使用AddChallengeView
(或另一个容器,在工作流程中重新创建内容),所以有
@ObservedObject var viewModel = AddChallengeViewModel()
在每次此类视图重新创建时创建 AddChallengeViewModel
类的新实例,因此之前的任何更改都将丢失。不过
@StateObject var viewModel = AddChallengeViewModel()
保留模型实例(第一次创建)并将其注入到在视图层次结构的同一位置重新创建的相同类型的新视图中。此外,新视图会收到有关同一模型的所有更改的通知。
实际上@StateObject
属性包装器对ObservableObject
的行为与@State
对值类型的行为相同。
【讨论】:
以上是关于发布值更改后不会触发 onReceive的主要内容,如果未能解决你的问题,请参考以下文章
当我在渲染视图后设置该输入类型的值时,为什么输入类型的更改事件不会触发?
Stickit:如何在每个模型后触发更改事件 -> 视图更改