Demo 地址: Use-popToViewController (opens new window)。
在 Push 了多个页面后,有时我们需要回到之前的某一页,这就比较麻烦了,我们需要确定返回的 ViewController 的位置。
比如:
可能有以下两种方式:
ViewController
类型以上两种 可能 写起来快捷一些,但这之中存在很多潜在问题。
退回两个页的代码大概如下:
saveBarButtonItem.rx.tap
.subscribe(onNext: { [unowned self] in
let destinationViewController = self.navigationController!.viewControllers[self.navigationController!.viewControllers.index(self.navigationController!.viewControllers.endIndex, offsetBy: -3)]
self.navigationController?.popToViewController(destinationViewController, animated: true)
})
.disposed(by: disposeBag)
直接读这段代码我们并不能理解我到底要回到的是具体哪个页面,当业务有调整时,比如中间又加了一页,== 这就很尴尬了,还要额外记得修改这里的 offset
。
或者是当这个设置手机号页面有多种转换场景,比如回到前两页,回到上一页,甚至是进入到一个新的页面。这些都用 index
写到一个页面就显得更加难理解了。
查找一下对应的 ViewController
类型的代码大概如下:
// SetNewMobileNumberViewController.swift
saveBarButtonItem.rx.tap
.subscribe(onNext: { [unowned self] in
let destinationViewController = self.navigationController!.viewControllers.first(where: { $0 is RootViewController })!
self.navigationController?.popToViewController(destinationViewController, animated: true)
})
.disposed(by: disposeBag)
判断一下对应的 ViewController
是不是 RootViewController
。
这样一来。 SetNewMobileNumberViewController
依赖了 RootViewController
,这是不友好的。
我们可能觉得应当用 Router
去做这件事,我觉得也不怎么合适,我们仍然需要在 SetNewMobileNumberViewController
写各种各样的返回场景,本质上还是依赖了 RootViewController
(只不过我们换成了对应的 URL
)。
将转场逻辑交给 RootViewController
处理 ,这可能是比以上两种方法更优雅的方案了。
VerifyCurrentMobileNumberViewController
和 SetNewMobileNumberViewController
不处理任何转场逻辑。只对外暴露产生的事件。
modifyPasswordButton.rx.tap
.flatMap { [unowned self] () -> Observable<()> in
let verifyCurrentMobileNumberViewController = VerifyCurrentMobileNumberViewController()
self.show(verifyCurrentMobileNumberViewController, sender: nil)
return verifyCurrentMobileNumberViewController.nextTap
}
.flatMap { [unowned self] () -> Observable<()> in
let setNewMobileNumberViewController = SetNewMobileNumberViewController()
self.show(setNewMobileNumberViewController, sender: nil)
return setNewMobileNumberViewController.saveTap
}
.subscribe(onNext: { [unowned self] in
self.navigationController?.popToViewController(self, animated: true)
})
.disposed(by: disposeBag)
self.navigationController?.popToViewController(self, animated: true)
这就清晰准确的表达了我们想要 pop 回哪个页面。