使用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 (将#修改为@)