I’ve been doing the page jump logic in the ViewModel, and the VC takes the target page and pushes it. During Code Review a few days ago, my colleague pointed out that theoretically there should be no UIKit related things in ViewModel.

I think that makes a lot of sense, but I don’t believe in putting page jump logic in VC, I think in MVVM VC acts as a ContainerView, manages the life cycle of the View, does dependency injection things like that and helps bind the View to the ViewModel, It’s the View layer. Only the push/present step of the page jump is in the View layer. The rest of the code, such as determining which page to jump to and what to do before jumping, should not be in the View layer.

However, UIKit objects in ViewModel are really uncomfortable, so I asked my foreign friends in Rx community in my broken English, but the result is not satisfactory:




RxCommunity1.png




RxCommunity2.png

They recommended an article and a library to me, which was not what I wanted, but I was very grateful for their kind help. The next day I wrote a Router:

typealias Completion = () -> Void enum PageMap { case DemoPage1 case DemoPage2(String) var vc: UIViewController { switch self { case .DemoPage: return DemoController1() case .DemoPage2(let title): return DemoController2(title: title) } } } enum Router { case Push(PageMap) case Present(PageMap) func go(form vc: UIViewController, animated: Bool = true, completion: Completion? = nil) { switch self { case .Push(let map): vc.navigationController? .pushViewController(map.vc, animated: animated) case .Present(let map): vc.presentViewController(map.vc, animated: animated, completion: completion) } } }Copy the code

With this Router, the ViewModel can provide the Driver, simply by subscribed to it in the VC.

There’s no problem you can’t solve with a layer of abstraction, Koko.