如果我通知操作已完成,是否应该使用 PublishSubject?

Tim*_*m J 5 ios swift rx-swift viper-architecture

我正在学习Viperw/ RxSwift

我想通知我PresenterviewDidLoad我的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)

Dan*_* T. 2

嗯...演示者的工作是收集用户操作,我不太确定我们是否应该将 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应该是vars,而是使用lets。这就是函数式反应式编程的“函数式”部分。