Reputation: 13
I am currently diving into RxSwift and I am trying to use it to update a TableView on a ViewController(.xib) with data that I get from a JSON and is encoded into a struct with Codable.
Here's my VM atm:
import Foundation
import RxCocoa
import RxSwift
protocol MenuViewModelProtocol {
func viewDidLoad()
}
class MenuViewModel: MenuViewModelProtocol {
private (set) var menu = MenuModel()
private let menuIntermediary = MenuDataIntermediary()
func viewDidLoad() {
debugPrint("MenuViewModel.viewDidLoad: Async request for menu was made")
requestAndSetMenuToIntermediary { (_ success) in
switch success {
case true:
debugPrint("MenuViewModel.requestAndSetMenuToIntermediary: Did get Menu successfully")
// print(self.menu) // -> menu is here
case false:
debugPrint("MenuViewModel.requestAndSetMenuToIntermediary: Did not get Menu successfully")
}
}
}
private func requestAndSetMenuToIntermediary(completion: @escaping (_ success: Bool) -> Void) {
menuIntermediary.jsonDataToMenuConversion { [weak self] (success) in
DispatchQueue.global().async {
guard let strongSelf = self else {
debugPrint("MenuViewModel.requestMenuToIntermediary: couldn't create a strong self reference")
completion(false)
return
}
guard let menu = menu else {
debugPrint("MenuViewModel.requestMenuToIntermediary: couldn't unwrap menu data")
completion(false)
return
}
strongSelf.menu = menu
// print(strongSelf.menu) // -> menu is here
completion(true)
}
}
}
}
The flow behing requestAndSetMenuToIntermediary is in short:
-> DataManager requests JSON from URL and returns a Data?
-> Intermediary Layer parses the JSON onto a Struct (with nested structs) using Codable and returns a Struct?
-> ViewModel gets the Struct? and unwraps it, being it ready for UI setup.
-> ??
My problem at '??' is to notify the VC that menu was updated in order to setup the TableView. Any suggestions? I've tried using PublishSubjects, BehaviorSubject combined with observables but I can't seem to make it work. I'm in doubt if it is syntax or something related to the background flow...
Thanks in advance! P.s - If more info is needed I can happily provide it, I was just trying to not make a very long post :p
Upvotes: 1
Views: 1465
Reputation: 21
I do not find any code about data binding in your code. Normally, if you are using RxSwift, you should create a data sequence and bound to your view. For Table View or Collection View, we love using RxDataSource
Observable
getting response from servermap
to Transform the dataIn you case, you should define a function to get menu model from server
private func getMenuModel() -> Obserable<MenuModel> {
/* the code getting response from server and transform to menu model */
}
Declare an Observable
let menuModelObservable: Observable<MenuModel>
init() {
menuModelObservable = getMenuModel()
}
Bind the data to your TableView
/* Your ViewController*/
override func viewDidLoad() {
super.viewDidLoad()
let viewModel = MenuViewModel()
viewModel.menuModelObservable.bind(to: tableView.rx.items(cellIdentifier: "Cell")) { index, model, cell in
cell.textLabel?.text = model
}.disposed(by: disposeBag)
}
Upvotes: 1