ios - 使用 RxSwift 的 UICollectionView 数据绑定 - iOS
问题描述
我有一个填充了数据模型的集合视图。当用户点击 collectionview 单元格时,我正在尝试更新嵌套模型的 bool 属性。反过来,collectionview 应该重新加载,并且 cell 应该更新为 bool 属性。但是模型中的属性更改不会更新集合视图。
//模型
struct MultiSelectionQuestionModel {
var header: String
var items: [Item]
}
extension MultiSelectionQuestionModel: SectionModelType {
typealias Item = MultiSelectionAnswerModel
init(original: MultiSelectionQuestionModel, items: [Item]) {
self = original
self.items = items
}
}
struct MultiSelectionAnswerModel {
var text: String
var isSelected: Bool = false //property to be updated
var cellType: CellType = .CustomType
}
//CollectionView 方法
func populateCells() {
let dataSource = RxCollectionViewSectionedReloadDataSource
<MultiSelectionQuestionModel>(
configureCell: { (_, collectionView, indexPath, item) in
guard let cell = collectionView
.dequeueReusableCell(withReuseIdentifier: item.cellType.rawValue, for: indexPath) as? MultiSelectionBaseCell else {
return MultiSelectionBaseCell()
}
cell.configure(item: item)
return cell
})
//handle collectionview cell tap
collectionView.rx.itemSelected.asObservable().map { (indexPath) -> Result in
//This method is called to update `isSelected` property. Once `isSelected` is updated. I am expecting the collectionview to reload and update the cell.
self.viewModel.toggleItemSelected(indexPath: indexPath)
}
collectionView.rx.setDelegate(self).disposed(by: disposeBag)
viewModel.items
.bind(to: collectionView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
}
//视图模型
struct MultiSelectionCollectionViewModel {
var items: BehaviorRelay<[MultiSelectionQuestionModel]> = BehaviorRelay(value: [])
var delegate:
init(questions: BehaviorRelay<[MultiSelectionQuestionModel]>) {
self.items = questions
}
//This method is called to update `isSelected` property. Once `isSelected` is updated. I am expecting the collectionview to reload and update the cell.
func toggleItemSelected(indexPath: IndexPath) {
let item = self.items.value[indexPath.section]
if let options = item.items as? [MultiSelectionAnswerModel] {
var optionItem = options[indexPath.row]
optionItem.isSelected = true // Collectionview reload Not working.
}
}
}
我刚开始学习 RxSwift。任何帮助表示赞赏。谢谢
解决方案
您必须调用items.accept(_:)
才能从 BehaviorRelay 中推出一个新数组。为此,您必须构建一个新数组。此外,BehaviorRelays(任何中继或主题)不应该是var
s;他们应该总是let
s。
另外,请记住,您实际上无法修改继电器中的阵列。相反,您将其替换为新数组。
这应该有效:
struct MultiSelectionCollectionViewModel {
let items: BehaviorRelay<[MultiSelectionQuestionModel]>
init(questions: BehaviorRelay<[MultiSelectionQuestionModel]>) {
self.items = questions
}
//This method is called to update `isSelected` property. Once `isSelected` is updated. I am expecting the collectionview to reload and update the cell.
func toggleItemSelected(indexPath: IndexPath) {
var multiSelectionQuestionModel = items.value // makes a copy of the array contained in `items`.
var item = multiSelectionQuestionModel[indexPath.section].items[indexPath.row] // makes a copy of the item to be modified
item.isSelected = true // modifies the item copy
multiSelectionQuestionModel[indexPath.section].items[indexPath.row] = item // modifies the copy of items by replacing the old item with the new one
items.accept(multiSelectionQuestionModel) // tells BehaviorRelay to update with the new array of items (it will emit the new array to all subscribers.)
}
}
protocol SectionModelType { }
enum CellType {
case CustomType
}
struct MultiSelectionQuestionModel {
var header: String
var items: [Item]
}
extension MultiSelectionQuestionModel: SectionModelType {
typealias Item = MultiSelectionAnswerModel
init(original: MultiSelectionQuestionModel, items: [Item]) {
self = original
self.items = items
}
}
struct MultiSelectionAnswerModel {
var text: String
var isSelected: Bool = false //property to be updated
var cellType: CellType = .CustomType
}
推荐阅读
- python-3.x - Spyder的控制台中没有graphviz输出
- java - 当android:launchMode =“singleInstance”时如何使用新数据启动相同的Activity?
- python - 无法在 OpenCV 中关闭视频窗口
- kubernetes - Kubernetes Google Cloud 上 GCR.io 注册表中的 ImagePullBackOff
- three.js - Three.js 光线投射与 Line 的交集
- javascript - onClick 事件未在 iOS Instagram In App Browser Meteor React JS Web App 内触发
- java - 在没有 youtube api 的情况下获得 YouTube 订阅者
- javascript - 如何从数组中删除新行字符串 [JS]
- java - 我应该如何设计我的应用程序流程来处理谷歌文档文件?
- python - 从输出中获取神经网络输入