Say I have the following SwiftRx (2.0.0-beta.4) MVVM situation:
I have 4 things:
ItemsManager has a func called items() that will return Items in an observable RxSwift way.
ItemsViewModel only needs to pass the items on up for now. Later maybe apply display logic on an Item attribute for the View Controller's sake (like displaying a date correctly.)
ItemListViewController will put the items in a table, one Item per row.
An Item has 4 attributes (like an identifier, date, ...) that will be displayed in the table row cell.
How does one set it up in the ItemsViewModel and ItemsManager so that when items are added, removed, changed in the manager that they go through the ItemsViewModel?
From reading the documentation and looking at the Rx.playground, it seems like the thing to use for now is an RxSwift PublishSubject< Item > or maybe an RxSwift map that is somehow subscribed to the manager's items()
How to do this well?
The ItemsManager has something like this right now:
func items() -> Observable<Item> {
// placeholder for now
return [Item(identification: "123", content: ""), Item(identification: "456", content:""), Item(identification: "789", content:"")].toObservable()
}
The View Model has this in it:
let items = Variable(/* how to subsribe to the items in the manager? */)
A contrived solution aka something which demonstrates a general approach and is simpler to understand is below:
import UIKit
import RxSwift
import RxCocoa
struct Item {
let identification: String
let content: String
}
struct ItemsManager {
let items: Variable<[Item]> = Variable<[Item]>(
[Item(identification: "some id1", content: "some content"),
Item(identification: "some id2", content: "some more content")]
)
}
struct ItemsViewModel {
let itemsManager = ItemsManager()
let myItems:Observable<[String]>
init() {
myItems = itemsManager.items
.map({ someArrayOfItems in
return someArrayOfItems.map {$0.content }
})
}
}
class ItemListViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
let itemsViewModel = ItemsViewModel()
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
itemsViewModel.myItems
.bindTo(tableView.rx_itemsWithCellIdentifier("itemListCell")) { (row, element, cell) in
guard let myCell: UITableViewCell = cell else {
return
}
myCell.textLabel?.text = element
}
.addDisposableTo(disposeBag)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With