I have a ViewModelType to bind UIViewController & ViewModel.
import Foundation
protocol ViewModelType {
associatedtype Input
associatedtype Output
func transform(input: Input) -> Output
}
The HomeViewModel conforms to ViewModelType and defines the Input and Output required, then it does the job returning the outputs based on the inputs.
For simplicity I have removed the repository and always returning failure for syncData task.
import Foundation
import RxSwift
import RxCocoa
class HomeViewModel: ViewModelType {
struct Input {
let syncData: Driver<Void>
}
struct Output {
let message: Driver<String>
}
func transform(input: Input) -> Output {
let fetching = input.syncData.flatMapLatest { _ -> Driver<String> in
return Observable<String>.from(optional: "Choose below options to proceed") // This message will be returned by server.
.delay(.seconds(1), scheduler: MainScheduler.instance)
.asDriverOnErrorJustComplete()
}
return Output(message: fetching)
}
}
I have a alert binder which takes a String.
The UIAlertController have a retry button on click of retry button I want to call syncData from Input of HomeViewModel How do I do that?
import UIKit
import RxSwift
import RxCocoa
class HomeViewController: UIViewController {
private let disposeBag = DisposeBag()
var viewModel = HomeViewModel()
override func viewDidLoad() {
super.viewDidLoad()
let viewDidAppear = rx.sentMessage(#selector(UIViewController.viewDidAppear(_:)))
.mapToVoid()
.asDriverOnErrorJustComplete()
// How to merge viewWillAppear & alert for callback of retry button?
let input = HomeViewModel.Input(syncData: viewDidAppear)
let output = viewModel.transform(input: input)
output.message.drive(alert)
.disposed(by: disposeBag)
}
var alert: Binder<String> {
return Binder(self) { (vc, message) in
let alert = UIAlertController(title: "Sync failed!",
message: message,
preferredStyle: .alert)
let okay = UIAlertAction(title: "Retry", style: .default, handler: { _ in
// how to call syncData of Input?
})
let dismiss = UIAlertAction(title: "Dismiss",
style: UIAlertAction.Style.cancel,
handler: nil)
alert.addAction(okay)
alert.addAction(dismiss)
vc.present(alert, animated: true, completion: nil)
}
}
}