I have an app using RxSwift following MVVM.
ViewController
import UIKit
import RxSwift
import RxCocoa
final class ProfileViewController: BaseViewController<ProfileView> {
var viewModel: Attachable<ProfileViewModel>!
var bindings: ProfileViewModel.Bindings {
let viewDidLoad = rx.sentMessage(#selector(UIViewController.viewDidLoad))
.mapToVoid()
.asDriverOnErrorJustComplete()
let viewWillAppear = rx.sentMessage(#selector(UIViewController.viewWillAppear))
.mapToVoid()
.asDriverOnErrorJustComplete()
let viewWillDisappear = rx.sentMessage(#selector(UIViewController.viewWillDisappear))
.mapToVoid()
.asDriverOnErrorJustComplete()
let logout = navigationItem.rightBarButtonItem?.rx.tap
.mapToVoid()
.asDriverOnErrorJustComplete()
return ProfileViewModel.Bindings(
connectStore: viewWillAppear.asDriver(),
disconnectStore: viewWillDisappear.asDriver(),
fetchProfileByUserId: viewDidLoad.asDriver()
)
}
private lazy var disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
configureView()
}
private func configureView() {
navigationItem.title = "Your account"
}
}
extension ProfileViewController: ViewModelAttaching {
func bind(viewModel: ProfileViewModel) -> ProfileViewModel {
return viewModel
}
}
ViewModel
import RxSwift
import RxCocoa
import ReSwift
final class ProfileViewModel: ViewModelType {
typealias Dependency = HasReduxStore & HasImagePicker
lazy var userID: String = __user__.id
let data = PublishSubject<ProfileHeaderViewModel>()
let endSession = PublishSubject<Void>()
private let dependency: Dependency
struct Bindings {
let connectStore: Driver<Void>
let disconnectStore: Driver<Void>
let fetchProfileByUserId: Driver<Void>
}
private lazy var disposeBag = DisposeBag()
init(dependency: Dependency, bindings: Bindings) {
self.dependency = dependency
bindings.connectStore
.asObservable()
.map { self }
.bind(onNext: dependency.store.subscribe)
.disposed(by: disposeBag)
bindings.disconnectStore
.asObservable()
.map { self }
.bind(onNext: dependency.store.unsubscribe)
.disposed(by: disposeBag)
bindings.fetchProfileByUserId
.asObservable()
.bind(onNext: dispatchFetchForProfileById)
.disposed(by: disposeBag)
}
private func dispatchFetchForProfileById() {
dependency.store.dispatch(FetchProfileByUserId(payload: userID))
}
}
extension ProfileViewModel: StoreSubscriber {
func newState(state: AppState) {
}
}
When my view is loaded I would expect bindings.fetchProfileByUserId to be invoked. However nothing is happening. I updated my binding to trigger on viewWillAppear instead and everything worked as expected.
I do not know why viewDidLoad is not working in this case.
You can add
.debug()to yourviewDidLoadchain, as well as a print() toviewDidLoadmethod to see what exactly happens, but by the looks of it, it seems you're setting up your bindings afterviewDidLoad(in theconfigureViewmaybe?) has fired so you never get any additional events, this happens only once during the view controller creation and would explain whyviewDidAppearworks.