iOS:如何使用MVVM将模型从视图模型传递到视图模型?

sma*_*rus 5 mvvm ios swift

假设我有一个模型Car,它在ViewModel1中实例化,具有以下初始属性:

ViewModel1

let car = Car(make: "McLaren", model: "P1", year: 2015)
Run Code Online (Sandbox Code Playgroud)

然后我需要在下一个视图控制器中完成汽车的其他信息.在跟踪MVVM时,在视图控制器之间传递模型的正确方法是什么?

使用MVC,它很简单,因为视图可以引用模型:

vc2.car = car
Run Code Online (Sandbox Code Playgroud)

下面是对该问题的伪尝试,但是我认为视图模型应该是私有的,并且只能由单个视图控制器访问.因此,以下尝试对我来说似乎不正确.

ViewController1

fileprivate let viewModel = ViewModel1()

func someMethod() ->  { 
    let car = self.viewModel.car 
    let vc2 = ViewController2()
    vc2.viewModel.car = car
    present(vc2, animated: true, completion: nil)
}
Run Code Online (Sandbox Code Playgroud)

ViewController2

let viewModel = ViewModel2()

func anotherMethod() {
    print(self.viewModel.car.make)  //prints "McLaren"

    viewModel.manipulateCar()       //adds additional information to the car object

    print(self.viewModel.car.color) //prints "Black"

    //Pass the finished car to the last view controller to display a summary
    let vc3 = ViewController3()
    vc3.viewModel.car = self.viewModel.car
}
Run Code Online (Sandbox Code Playgroud)

我想知道上面显示的内容是否是使用MVVM时的好方法,或者如果不是,在视图控制器之间传递汽车的最佳方法是什么?

编辑

这个问题与Class vs Struct没有关系.上面的MVC示例暗示它将成为一个类(因为它是一个引用),并且它在多个视图控制器之间传递以完成对象的更多部分.

这是一个关于如何在跟踪MVVM时在视图控制器之间传递模型以及视图模型是否应该是视图控制器专用的问题.

对于MVVM,视图控制器不应该引用模型,因此不应该有变量var car: Car?.因此,您不应该看到:

let vc2 = ViewController2()
vc2.car = car
Run Code Online (Sandbox Code Playgroud)

看到这个会不正确吗?

let vc2 = ViewController2()
vc2.viewModel.car = car
Run Code Online (Sandbox Code Playgroud)

Dan*_* T. 15

这个问题与RxSwift无关,甚至与MVVM和MVC无关.这是一个Class vs Struct问题.(请注意,当模型是结构时,您的注释"使用MVC,因为视图可以引用模型很简单"是不正确的,因为您无法将引用传递给结构体.)

如何解决此问题完全取决于您从视图控制器转换到视图控制器的方式.

当视图控制器负责转换时.

当视图控制器负责转换时,每个视图控制器将负责制作下一个视图控制器,并且每个视图模型将负责制作下一个视图模型.通过让"父"视图模型监听"子"视图模型(通过委托,回调闭包或反应可观察)来完成传递模型.

视图控制器可以通过segue或"老式方式"通过直接创建和呈现下一个视图控制器,或者到达它的容器视图控制器(例如导航VC)并告诉它进行转换来进行转换.

当协调员负责过渡时.

转换的一个新趋势是让协调员类来处理它而不是视图控制器.使用这个想法,协调器保存模型,并根据需要创建视图控制器.视图模型然后与协调器对话而不是(可能创建和)彼此交谈.这样,视图控制器彼此独立.

您可以使用任何委托,闭包回调或Rx Observables让视图模型与协调器对话.


从您的编辑更新:

你问过它是否不正确let vc2 = ViewController2(); vc2.viewModel.car = car.答案是肯定的,这是不正确的,但接近.

如果视图控制器负责转换,那么你会看到这是:

// in view controller 1
let vc2 = ViewController2()
vc2.viewModel = self.viewModel.viewModel2
Run Code Online (Sandbox Code Playgroud)

如果你正在使用协调员,那么你会看到类似的东西:

// in coordinator
let vm2 = ViewModel(car: self.car)
let vc2 = ViewController2(viewModel: vm2)
Run Code Online (Sandbox Code Playgroud)

视图模型背后的关键思想并不是它是私有的,它不是必须的.关键的想法是它是视图控制器所持有的唯一非视图对象.您可以将其视为"模型控制器".


Sof*_*ner 5

长话短说。只需将模型包装在child视图模型中。

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let detailsViewModel = viewModel.detailsViewModel(for: indexPath.row)
    let detailsViewController = DetailsViewController(viewModel: detailsViewModel) 
    present(detailsViewController, animated: true, completion: nil)
}
Run Code Online (Sandbox Code Playgroud)

在视图模型中detailsViewModel声明master如下:

func detailsViewModel(for index: Int) -> DetailsViewModel {
    return DetailsViewModel(car: cars[index])
}
Run Code Online (Sandbox Code Playgroud)

没有使用协调器。