[英]RxSwift: How to populate the data in collection view cell inside the table view using ViewModel?
I do have following structure:我确实有以下结构:
- TableView
-- Custom Table View Cell
--- CollectionView
---- Custom CollectionView Cell
I want to understand that how can I pass the data from / using view model in this structure with RxSwift - MVVM Structure.我想了解如何使用 RxSwift - MVVM 结构在此结构中的视图 model 传递数据/使用视图 model。
Whenever I do get response from API it should update the data in table view rows and associated collection view cell respectively.每当我收到 API 的响应时,它应该分别更新表视图行和关联的集合视图单元格中的数据。
Here is an example I wrote just now to demonstrate how you can use RxSwift to do what you want.这是我刚刚写的一个例子,用来演示如何使用 RxSwift 做你想做的事。 Important Note: This is a rough example, not optimally written and not tested, I just wrote it using a text editor hope it helps you out.
重要提示:这是一个粗略的示例,没有经过优化编写和测试,我只是使用文本编辑器编写的,希望对您有所帮助。 if not I will try to polish it when I have some more time.
如果没有,我会在有更多时间时尝试打磨它。
class MyViewModel {
// Lets say TableData is your model for the tableView data and CollectionData for your collectionView
public let tableData : PublishSubject<[TableData]> = PublishSubject()
public let collectionData : PublishSubject<[CollectionData]> = PublishSubject()
private let disposeBag = DisposeBag()
func fetchData() {
// Whenever you get an update from your API or whatever source you call .onNext
// Lets assume you received an update and stored them on a variable called newShopsUpdate
self.tableData.onNext(newTableDataUpdate)
self.collectionData.onNext(newCollectionDataDataUpdate)
}
}
class MyViewController: UIViewController {
var tableData: BehaviorRelay<[TableData]> = BehaviorRelay(value: [])
var collectionData: BehaviorRelay<[CollectionData]> = BehaviorRelay(value: [])
let viewModel = MyViewModel()
override func viewDidLoad() {
super.viewDidLoad()
// Setup Rx Bindings
viewModel
.tableData
.observeOn(MainScheduler.instance)
.bind(to: self.tableData)
.disposed(by: DisposeBag())
viewModel
.collectionData
.observeOn(MainScheduler.instance)
.bind(to: self.collectionData)
.disposed(by: DisposeBag())
// Register yours Cells first as usual
// ...
// Setting the datasource using RxSwift
tableData.bind(to: tableView.rx.items(cellIdentifier: "yourCellIdentifier", cellType: costumeTableViewCell.self)) { row, tableData, cell in
// Set all the cell properties here
// Lets also assume you have you collectionView inside one of the cells
cell.tableData = tableData
collectionData.bind(to: cell.collectionView.rx.items(cellIdentifier: "yourCellIdentifier", cellType: costumeCollectionViewCell.self)) { row, collectionData, cell in
// Set all the cell properties here
cell.collectionData = collectionData
}.disposeBag(by: DisposeBag())
}.disposed(by: DisposeBag())
}
}
The simplest solution is to use an array of arrays.最简单的解决方案是使用 arrays 数组。
For example.例如。 Let's assume your API returns:
假设您的 API 返回:
struct Group: Decodable {
let items: [String]
}
Then your view model would be as simple as this:那么你的观点 model 会像这样简单:
func tableViewItems(source: Observable<[Group]>) -> Observable<[[String]]> {
return source
.map { $0.map { $0.items } }
}
When creating your cell, you can wrap the inner array into an observable with Observable.just()
like this:创建单元格时,您可以使用
Observable.just()
将内部数组包装成一个可观察对象,如下所示:
// in your view controller's viewDidLoad for example.
tableViewItems(source: apiResponse)
.bind(to: tableView.rx.items(cellIdentifier: "Cell", cellType: CollectionTableViewCell.self)) { _, element, cell in
Observable.just(element)
.bind(to: cell.collectionView.rx.items(cellIdentifier: "Cell", cellType: UICollectionViewCell.self)) { _, element, cell in
let label = (cell.viewWithTag(6969) as? UILabel) ?? UILabel()
label.tag = 6969
label.text = element
label.sizeToFit()
cell.addSubview(label)
}
.disposed(by: cell.disposeBag)
}
.disposed(by: dispsoeBag)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.