Tim*_*m J 5 ios swift rx-swift viper-architecture
我正在学习Viper
w/ RxSwift
。
我想通知我Presenter
在viewDidLoad
我的ViewController
.
为此,我有以下几点:
class LoginPresenter {
weak var view: LoginView?
var interactor: LoginUseCase?
var router: LoginRouter?
private(set) var viewDidLoad = PublishSubject<Void>()
private lazy var disposeBag = DisposeBag()
required init(view: LoginView?, interactor: LoginUseCase?, router: LoginRouter?) {
self.view = view
self.interactor = interactor
self.router = router
viewDidLoad
.subscribe(onNext: { _ in
// do something on viewDidLoad
}).disposed(by: disposeBag)
}
}
Run Code Online (Sandbox Code Playgroud)
class LoginViewController: UIViewController {
var presenter: LoginPresenter?
override func viewDidLoad() {
super.viewDidLoad()
presenter?.viewDidLoad.onNext(())
}
}
Run Code Online (Sandbox Code Playgroud)
一旦我的视图加载,我就会打电话presenter?.viewDidLoad.onNext(())
然后,我可以触发演示者中的任何操作,例如呼叫我router
以确保配置导航或呼叫我的interactor
.
我应该PublishSubject
为此使用 a 吗?或者RxSwift
有更适合的类型吗?
我觉得这种方法意味着我最终会得到类似的结果
viewDidLoad
.subscribe(onNext: { _ in
self.router?.viewDidLoad.onNext(())
}).disposed(by: disposeBag)
Run Code Online (Sandbox Code Playgroud)
嗯...演示者的工作是收集用户操作,我不太确定我们是否应该将 viewDidLoad 视为用户操作。无论如何,线框(处理路由)不需要知道 viewDidLoad 何时被调用;它的工作是呈现新屏幕,并且您无法在 viewDidLoad 中呈现屏幕。
也就是说,您可以在 ViewController 的 Presenter didSet 中设置连接:
final class ViewController: UIViewController {
var presenter: Presenter? {
didSet {
guard let presenter = presenter else { viewDidLoadDisposable.dispose(); return }
viewDidLoadDisposable.disposable = rx.methodInvoked(#selector(viewDidLoad))
.map { _ in }
.bind(to: presenter.viewDidLoad)
}
}
let viewDidLoadDisposable = SerialDisposable()
deinit {
viewDidLoadDisposable.dispose()
}
}
final class Presenter {
let viewDidLoad = PublishSubject<Void>()
}
Run Code Online (Sandbox Code Playgroud)
但一般来说,在 viewDidLoad 中,presenter 和 viewController 元素通常绑定在一起,因此上面的代码有一种非常不自然的感觉。
另外,Observables、Subjects 和 DisposeBag不应该是var
s,而是使用let
s。这就是函数式反应式编程的“函数式”部分。