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

Should I use a PublishSubject if I am notifying an action is complete?

我正在学习 Viper w/ RxSwift

我想通知我的 Presenter 我的 ViewController 中调用了 viewDidLoad

为此,我有以下内容:

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)
    }
}
class LoginViewController: UIViewController {

    var presenter: LoginPresenter?

    override func viewDidLoad() {
        super.viewDidLoad()

        presenter?.viewDidLoad.onNext(())
    }
}

加载我的视图后,我将调用 presenter?.viewDidLoad.onNext(())

然后我可以在演示者中触发任何操作,例如呼叫我的 router 以确保导航已配置或我的 interactor.

我应该为此使用 PublishSubject 吗?或者 RxSwift 有更适合的类型吗?

我觉得这种方法意味着我最终会得到类似

的东西
        viewDidLoad
            .subscribe(onNext: { _ in
                self.router?.viewDidLoad.onNext(())
            }).disposed(by: disposeBag)

嗯...Presenter 的工作是收集用户操作,我不确定我们是否应该将 viewDidLoad 视为 user 操作。并且在任何情况下,线框(处理路由)都不需要知道何时首先调用 viewDidLoad;它的工作是呈现新屏幕,您不能在 viewDidLoad 中呈现屏幕。

也就是说,您可以在 ViewController 的演示者 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>()
}

不过一般来说,presenter 和 viewController 元素通常是在 viewDidLoad 中绑定在一起的,所以上面的代码给人一种很不自然的感觉。

此外,Observables、Subjects 和 DisposeBag 应该 而不是 var,请改用 let。那是函数式反应式编程的“函数式”部分。