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 your viewDidLoad
chain, as well as a print() to viewDidLoad
method to see what exactly happens, but by the looks of it, it seems you're setting up your bindings after viewDidLoad
(in the configureView
maybe?) has fired so you never get any additional events, this happens only once during the view controller creation and would explain why viewDidAppear
works.