【问题标题】:Sharing ViewModel between SwiftUI components在 SwiftUI 组件之间共享 ViewModel
【发布时间】:2019-12-20 11:13:43
【问题描述】:

我想为使用 SwiftUI 和 Combine 实现的架构实现导航器/路由器。简而言之,View 将与Router 共享viewModel。当View 触发viewModel 上的更改时,Router 应导航到新工作表。

这是我的代码的一个版本,我将viewModelView 直接传递给Router。有什么不对的吗?我最大的疑问是,由于我在RouterView 上都使用了@ObservedObject,因此创建了viewModel 的两个不同实例。

查看模型

class BootViewModel:ObservableObject{
    @Published var presentSignIn = false
}

查看

struct BootView: View {

    @ObservedObject var viewModel:BootViewModel
    var navigator:BootNavigator<BootView>? = nil

    init(viewModel:BootViewModel) {
        self.viewModel = viewModel
        self.navigator = BootNavigator(view: self, viewModel: viewModel)
        self.navigator.setSubscriptions()
    }

    var body: some View {
        VStack{
            Text("Hello")
            Button("Button"){
                self.viewModel.presentSignIn.toggle()
            }
        }
    }
}

导航器

class BootNavigator<T:View>{
    var view:T? = nil
    @ObservedObject var viewModel:BootViewModel

    init(view:T, viewModel:BootViewModel) {
        self.view = view
        self.viewModel = viewModel
    }

    func setSubscriptions(){
        subscribe(onSigninPressed: $viewModel.presentSignIn)
    }


    func subscribe(onSigninPressed : Binding<Bool>){
        _ = view.sheet(isPresented: $viewModel.presentSignIn){
            SignInView()
        }
    }
}
  • 为什么从未显示SignInView
  • 没有考虑到通常不需要使用带有 swiftUI 的路由器这一事实(我主要是在做一个练习)......这个实现有什么问题吗?

【问题讨论】:

    标签: swift swiftui combine


    【解决方案1】:

    这个

    view.sheet(isPresented: $viewModel.presentSignIn){
        SignInView()
    

    必须位于 body 中的某个位置(直接或通过计算属性或函数)但在主体的 ViewBuilder 中

    【讨论】:

    • 你介意分享一个官方文档的链接吗?我找不到任何引用这个约束的东西
    【解决方案2】:

    我必须在这里指出一些注意事项:

    值类型

    UIView 和 SwiftUI View 之间存在差异。所有 SwiftUI Views 都是值类型!因此,当您传递它们时,它们会被复制。请注意这一点。

    单实例

    如果您想为整个应用程序提供像常规 导航器 这样的单个实例,您可以使用单例模式。但是在 SwiftUI 世界中有一种更好的方法,称为 @Environment 对象。您可以利用这一点。

    触发视图刷新

    要刷新视图(包括呈现某些内容),您必须在var body 内部 编码。但可以直接通过函数等间接写入。

    【讨论】:

    • 您介意使用使用@Environment 处理导航器的代码改进答案吗?我有点困惑,因为我的每个视图都会有他们专用的导航器......
    • 看看this article
    • 抱歉,您的问题需要大量基于意见的信息,而这在 SO 上是不允许的。我试图指出主题,你应该自己跟着尾巴走。但是,如果您对此有任何疑问,我的朋友,我将非常乐意提供帮助。
    猜你喜欢
    • 1970-01-01
    • 2023-03-13
    • 2019-07-02
    • 2010-11-12
    • 2011-05-24
    • 2015-12-06
    • 1970-01-01
    • 2022-11-10
    • 2020-09-11
    相关资源
    最近更新 更多