使用RxSwift-iOS的UICollectionView数据绑定

使用RxSwift-iOS的UICollectionView数据绑定,ios,swift,uicollectionview,rx-swift,Ios,Swift,Uicollectionview,Rx Swift,我有一个用数据模型填充的collectionview。当用户点击collectionview单元格时,我试图更新嵌套模型的bool属性。反过来,collectionview应该重新加载,单元格应该更新为bool属性。但是模型中的属性更改不会更新collectionview //模型 struct MultiSelectionQuestionModel { var header: String var items: [Item] } extension MultiSelectionQue

我有一个用数据模型填充的collectionview。当用户点击collectionview单元格时,我试图更新嵌套模型的bool属性。反过来,collectionview应该重新加载,单元格应该更新为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)
}
func populateCells(){
让dataSource=RxCollectionViewSectionedReloadDataSource
(
configureCell:{(\ux,collectionView,indexPath,item)位于
guard let cell=collectionView
.dequeueReuseAbleCell(带ReuseIdentifier:item.cellType.rawValue,for:indexPath)作为?MultiSelectionBaseCell else{
返回MultiSelectionBaseCell()
}
cell.configure(项:项)
返回单元
})
//句柄集合视图单元格点击
collectionView.rx.itemSelected.asObservable().map{(indexPath)->导致
//调用此方法以更新'isSelected'属性。一旦更新了'isSelected',我希望collectionview重新加载并更新单元格。
self.viewModel.toggleItemSelected(indexPath:indexPath)
}
collectionView.rx.setDelegate(自).disposed(由:disposeBag)
viewModel.items
.bind(到:collectionView.rx.items(数据源:数据源))
.处置(由:处置人)
}
//视图模型

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. 
        } 
    }
}
struct MultiSelectionCollectionViewModel{
变量项:BehaviorRelay=BehaviorRelay(值:[])
变量代表:
初始化(问题:行为规则){
self.items=问题
}
//调用此方法以更新'isSelected'属性。一旦更新了'isSelected',我希望collectionview重新加载并更新单元格。
func toggleItemSelected(indexPath:indexPath){
让item=self.items.value[indexPath.section]
如果let options=item.items as?[MultiSelectionAnswerModel]{
var optionItem=options[indexPath.row]
optionItem.isSelected=true//Collectionview重新加载不工作。
} 
}
}

我刚开始学习RxSwift。感谢您的帮助。谢谢

您必须调用
项。接受(:)
以将新数组从您的行为延迟中推出。为此,必须构建一个新阵列。此外,行为关系(任何继电器或受试者)不得为
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
}
struct MultiSelectionCollectionViewModel{
让项目:行为关系
初始化(问题:行为规则){
self.items=问题
}
//调用此方法以更新'isSelected'属性。一旦更新了'isSelected',我希望collectionview重新加载并更新单元格。
func toggleItemSelected(indexPath:indexPath){
var multiSelectionQuestionModel=items.value//复制“items”中包含的数组。
var item=multiSelectionQuestionModel[indexPath.section].items[indexPath.row]//创建要修改的项的副本
item.isSelected=true//修改项目副本
multiSelectionQuestionModel[indexPath.section].items[indexPath.row]=item//通过将旧项替换为新项来修改项的副本
items.accept(multiSelectionQuestionModel)//告诉BehaviorRelay使用新的项目数组进行更新(它将向所有订阅者发出新数组。)
}
}
协议节模型类型{}
枚举单元类型{
案例自定义类型
}
结构多选问题模型{
变量头:字符串
可变项目:[项目]
}
扩展多选问题模型:SectionModelType{
typealias项=多选回答模型
初始(原始:MultiSelectionQuestionModel,items:[项目]){
自我=原创
self.items=项目
}
}
结构多选择应答模型{
变量文本:字符串
var isSelected:Bool=false//要更新的属性
变量cellType:cellType=.CustomType
}

请记住,您实际上无法修改中继中的阵列
-是。我认为,由于行为相关性是变化的传播,我们无法替换已经释放的值。