使用 RxSwift 的 UICollectionView 数据绑定 - iOS
Posted
技术标签:
【中文标题】使用 RxSwift 的 UICollectionView 数据绑定 - iOS【英文标题】:UICollectionView databinding using RxSwift - iOS 【发布时间】:2020-01-10 15:12:50 【问题描述】:我有一个填充了数据模型的集合视图。当用户点击 collectionview 单元格时,我正在尝试更新嵌套模型的 bool 属性。反过来,collectionview 应该重新加载,并且 cell 应该更新为 bool 属性。但是模型中的属性变化并没有更新collectionview。
//型号
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。任何帮助表示赞赏。谢谢
【问题讨论】:
【参考方案1】:您必须调用 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
【讨论】:
keep in mind that you can't actually modify the array in the relay
- 是的。我认为由于 behaviorRelay 是变化的传播,我们不能替换已经发出的值。以上是关于使用 RxSwift 的 UICollectionView 数据绑定 - iOS的主要内容,如果未能解决你的问题,请参考以下文章
如何在 UICollection 补充视图中使用 UIButton?
如何使用装饰器视图在 uicollection 视图中实现所需的设计
UICollection 在使用 Swift 3 显示图像时非常慢
在 UITableviewCell 中使用 UICollection 视图时未调用 UICollectionView 委托方法“didSelectItemAtIndexPath”