使用SwiftUI作为视图层的MVVM应用中的导航流程

问题描述

我发现很难为SwiftUI应用程序确定最佳的架构模式,但是目前,我坚持使用MVVM,因为从概念上讲,这很合适。

我试图避免SwiftUI层对业务逻辑和导航结构有太多了解,但正在努力决定如何最好地实现这一目标。

这是原型视图模型(没有用于导航的实现):

@dynamicMemberLookup
final class PatientListViewModel: ViewModelType {
    struct State {
        var patients: [PatientSummaryViewModel]
    }
    @Published var state: State = State(patients: []) {
        willSet { print("Received: \(newValue)") }
    }
    
    enum Input {
        case onNewPatient
    }
    
    private let service: PatientServiceType
    private var cancellables = Set<AnyCancellable>()
    
    init(service: PatientServiceType) {
        self.service = service
        
        service.fetchAll()
            .receive(on: DispatchQueue.main)
            .map { patients in
                patients.map {
                    PatientSummaryViewModel(patient: $0)
                }
            }
            .sink { [weak self] patientViewModel in
                self?.state.patients = patientViewModel
            }
            .store(in: &cancellables)
    }
    
    func action(_ input: Input) {
        switch input {
        case .onNewPatient:
            print("Create new view and associated viewModel here but how does SwiftUI access it?")
        }
    }
    
    subscript<Value>(dynamicMember keyPath: KeyPath<State,Value>) -> Value {
        state[keyPath: keyPath]
    }
}

关联的SwiftUI视图:

struct PatientListView: View {
    @ObservedObject var viewModel: PatientListViewModel
    
    var body: some View {
        NavigationView {
            List(viewModel.patients) { viewModel in
                
                NavigationLink(
                    destination:
                        PatientSummaryView(viewModel: viewModel),label: {
                        PatientCell(patient: viewModel.patient)
                    })
                
            }
            .navigationBarItems(leading: EditButton(),trailing: Button(action: {
                                    // call to viewmodel to get new view and correctly constructed viewModel
                                },label: { Image(systemName: "plus")
                                                    .font(.title2)
                                                 }))
            .navigationBarTitle("Patients")
        }
    }
}

目前,有几种解决方案可供展示:

  1. 修改动作(_ input :)以原位创建View,然后将其返回给调用它的View。并非所有动作都需要进行导航,因此我需要添加@discardableresult,其中许多动作必须返回EmptyView(),然后我需要做一些与类型擦除视图有关的舞蹈

  2. 修改视图模型状态内部结构以包括“下一个视图”属性,该属性在需要新视图时由action(_ :)更新。尽管将状态保持在一个地方的想法很吸引人,但这还是有点笨拙

  3. 最后,我对传递给视图模型并用于构造所需视图的回调/关闭有一些模糊的想法,但由于我仍然发现关闭语法令人困惑,因此我很难将其可视化使用Views

欢迎想法,指点和批评! ;-)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...