I have a ViewController
and ViewModel
. Here I am using the .subscribe()
method too many times to bind title property and etc.
As you can see in the bindActions
method I am subscribing to action.fetchCaregivers
inside and calling fetchCaregivers()
.
How can I make this code a bit better?
import UIKit
import RxDataSources
class PatientCaregiversViewController: ViewController {
var tableView: UITableView!
var viewModel: PatientCaregiversViewModel!
static func initalise() -> PatientCaregiversViewController {
let viewController = PatientCaregiversViewController()
let dataProvider = AlternateCaregiverRemoteRepo()
viewController.viewModel = PatientCaregiversViewModel(dataProvider: dataProvider)
return viewController
}
override func setupView() {
super.setupView()
setupTableView()
configureEmptyDataSetView()
}
override func bindViews() {
super.bindViews()
// Bind State
viewModel.state.title
.subscribe(onNext: { [weak self] text in
self?.title = text
}).disposed(by: viewModel.disposeBag)
// Bind View
viewModel.state.displayData
.bind(to: tableView.rx.items(dataSource: getDataSource()))
.disposed(by: disposeBag)
bindEmptyDataSet(observable: viewModel.state.emptyDataSetState)
.subscribe(onNext: { [weak self] in
self?.viewModel.action.fetchCaregivers.onNext(())
}).disposed(by: viewModel.disposeBag)
}
override func finishedLoading() {
super.finishedLoading()
viewModel.action.fetchCaregivers.onNext(())
}
}
extension PatientCaregiversViewController {
private func setupTableView() {
tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.tableHeaderView = UIView(frame: .zero)
tableView.tableFooterView = UIView(frame: .zero)
view.addSubview(tableView)
[tableView.topAnchor.constraint(equalTo: view.topAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor)]
.forEach({ $0?.isActive = true })
view.layoutIfNeeded()
}
func getDataSource() -> RxTableViewSectionedReloadDataSource<RxAnimatableTableSectionModel>! {
let dataSource = RxTableViewSectionedReloadDataSource<RxAnimatableTableSectionModel>(
configureCell: { [weak self] dataSource, tableView, indexPath, item in
switch item {
case let model as CaregiverInviteCellModel:
let cell = tableView.dequeueReusableCell(withIdentifier: "CaregiverInviteTableViewCell", for: indexPath) as! CaregiverInviteTableViewCell
cell.data = model
return cell
default:
return UITableViewCell()
}
})
return dataSource
}
}
import Foundation
import RxSwift
import RxCocoa
import RxDataSources
class PatientCaregiversViewModel: ViewModel {
struct Action {
let fetchCaregivers = PublishSubject<()>()
let inviteCaregiver = PublishSubject<()>()
let refreshList = PublishSubject<()>()
}
struct State {
let title = BehaviorRelay<String>.init(value: "CAREGIVERS")
let displayData = BehaviorRelay<[RxAnimatableTableSectionModel]>(value: [])
let emptyDataSetState = BehaviorRelay<DataState>.init(value: .loading(title: "", message: ""))
let showInviteLink = BehaviorRelay<Bool>.init(value: false)
let invitTapped = PublishSubject<()>()
}
var action: Action
var state: State
var dataProvider: AlternateCaregiverRemoteRepo
init(dataProvider: AlternateCaregiverRemoteRepo) {
self.dataProvider = dataProvider
action = Action()
state = State()
super.init()
bindActions()
}
}
// MARK:- PRIVATE METHODS.
extension PatientCaregiversViewModel {
private func bindActions() {
action.fetchCaregivers
.subscribe(onNext: { [weak self] _ in
self?.fetchCaregivers()
}).disposed(by: disposeBag)
action.inviteCaregiver
.subscribe(onNext: { [weak self] _ in
self?.state.invitTapped.onNext(())
}).disposed(by: disposeBag)
}
private func fetchCaregivers() {
state.emptyDataSetState.accept(loadingState)
dataProvider.getAllCaregivers()
.subscribe { [weak self] (event) in
guard let this = self else { return }
this.state.emptyDataSetState.accept(.failed(title: this.failedTitle, message: this.failedTitle))
}.disposed(by: disposeBag)
}
}
// MARK:- MESSAGES.
extension PatientCaregiversViewModel {
var loadingState: DataState {
let title = "Loading Caregivers"
let message = "Please wait while we load caregivers for you."
return DataState.loading(title: title, message: message)
}
var noDataState: DataState {
let title = "No Caregiver linked"
let message = "Please invite an alternate caregiver by clicking the invite button."
return DataState.noData(title: title, message: message)
}
var failedTitle: String {
return "Failed to get Caregivers"
}
}
```
ViewController
type? What library provides theViewModel
type? Put imports on the code to show what libraries you are depending on. \$\endgroup\$