之前我一直在 ViewModel 中處理頁面跳轉邏輯,VC 直接拿到目標頁面進行 push/present灾炭。前些天 Code Review 時茎芋,同事指出理論上 ViewModel 里不應該出現(xiàn)跟 UIKit 相關的東西。
我覺得很有道理蜈出,但我也不贊成把頁面跳轉邏輯寫到 VC 里田弥,我認為在 MVVM 中 VC 中充當了一個 ContainerView 的角色,管理 View 的生命周期铡原,做一些依賴注入之類的事情輔助 View 和 ViewModel 的綁定偷厦,它是 View 層的商叹。頁面跳轉中只有 push/present 這一步是 View 層的,其他諸如通過一些邏輯判斷該跳轉到哪個頁面只泼、跳轉之前需要做什么操作之類的代碼不該放在 View 層剖笙。
但 ViewModel 中出現(xiàn) UIKit 對象這一點也確實讓人難受,于是我用我蹩腳的英語詢問了 Rx 社區(qū)的外國友人请唱,但結果并不盡如人意:
RxCommunity1.png
RxCommunity2.png
他們向我推薦了一篇文章和一個庫弥咪,雖然并不是我想要的,但還是很感謝他們的熱心幫助十绑。第二天我自己寫了一個 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)
}
}
}
有了這個 Router聚至,ViewModel 就可以提供 Driver<Router>,只要在 VC 里訂閱它就好本橙。
果然沒有什么問題是加一層抽象不能解決的扳躬,科科。