我有两个带有嵌套视图模型的嵌套视图,需要确保对它们进行验证.

从本质上讲,ViewA有一个表单、一个提交按钮和一个子视图(ViewB)--ViewB的ViewModel包含在ViewBThis architecture cannot change due to boring business reasons中,ViewB有一些表单域.在启用提交按钮之前,我需要确保所有字段在视图A和视图B中都有效.

我似乎想不出如何做到这一点,因为ViewB中的任何更改都不会触发Viewa刷新

以下是一些简化的代码,作为粗略的示例

    class ViewModelB: ObservableObject {
    @Published var text = ""
    @Published var textTwo = ""
    
    func isValid() -> Bool {
        !text.isEmpty && !textTwo.isEmpty
    }
}

class ViewModelA: ObservableObject {
    @Published var text = ""
    @ObservedObject var addressViewModel: ViewModelB = ViewModelB()

    func isValid() -> Bool {
        print("is Valid called")
        return !text.isEmpty && addressViewModel.isValid()
    }
}
struct AddressView: View {
    @ObservedObject var viewModel: ViewModelB

    init(addressModel:ViewModelB) {
        self.viewModel = addressModel
    }
    var body: some View {
        TextField("View B Text", text: $viewModel.text)
        TextField("View B TextTwo", text: $viewModel.textTwo)
    }
}

struct ContentView: View {
    @StateObject var viewModel: ViewModelA = ViewModelA()

    var body: some View {
        VStack {
            TextField("View A Text", text: $viewModel.text)
            AddressView(addressModel: viewModel.addressViewModel)
            Button("Apply Button") {
                print("Button tapped!")
            }.disabled(!viewModel.isValid() || !viewModel.addressViewModel.isValid())
        }
    }
}

推荐答案

将AddressView中的ViewModelB更改为Binding而不是ObservedObject,使其在ViewModelA Published中而不是ObservedObject中可以解决问题.

原因是SwiftUI用于观察更改的机制只在一个级别的对象上起作用,并且不会自动将更新传播到嵌套在其中的对象.

请在下面找到完整的代码.

class ViewModelB: ObservableObject {
    @Published var text = ""
    @Published var textTwo = ""
    
    func isValid() -> Bool {
        !text.isEmpty && !textTwo.isEmpty
    }
}

class ViewModelA: ObservableObject {
    @Published var text = ""
    @Published var addressViewModel: ViewModelB = ViewModelB()
    
    func isValid() -> Bool {
        print("is Valid called")
        return !text.isEmpty && addressViewModel.isValid()
    }
}

struct AddressView: View {
    @Binding var viewModel: ViewModelB
    
    var body: some View {
        TextField("View B Text", text: $viewModel.text)
        TextField("View B TextTwo", text: $viewModel.textTwo)
    }
}

struct ContentView: View {
    @StateObject var viewModel: ViewModelA = ViewModelA()
    
    var body: some View {
        VStack {
            TextField("View A Text", text: $viewModel.text)
            AddressView(viewModel: $viewModel.addressViewModel)
            Button("Apply Button") {
                print("Button tapped!")
            }.disabled(!viewModel.isValid() || !viewModel.addressViewModel.isValid())
        }
    }
}

Swift相关问答推荐

如何设置两个不同的视图模型以在我的SwiftUI应用程序中使用相同的数据源?

并发访问SWIFT中数组的非重叠子范围

如何让ScrollView缩小到合适的大小,并在没有黑客攻击的情况下占用最小空间

当计数大于索引时,索引超出范围崩溃

仅当单击UIButton时才调用计时器函数

SwiftUI路径平滑连接两条线

DispatchQueue.main.asyncAfter 等同于 Swift 中的 struct 化并发?

我怎样才能缩短(提高效率)这段代码?

如何在 Combine 合并运算符的输出上使用 eraseToAnyPublisher

快速递归:函数与闭包

为什么 performSegue() 不调用 shouldPerformSegue()

带有屏幕参数的 NSWindow 初始化程序在初始化时导致致命错误

使用协议捕获 SwiftUI 视图

如何处理永远不会失败的 String.Encoding 初始化程序?

在 Swift 中从 HTML 生成带有图像的 PDF 而不显示打印界面

MKAnnotation Swift

将强制向下转换视为可选将永远不会产生零

如何在今天的扩展(iOS)中访问 CoreData 模型

自定义 Google 登录按钮 - iOS

如何在 iOS 上的 Swift 中获取 sharedApplication?