简体   繁体   中英

RxDataSource: Nest CollectionView in TableViewCell

Definition for Section:

enum ItemDetailTableViewItem {
    case itemInfoTopItem(info: ItemDetailViewModelPlus)
    case itemHintItem(hint: ItemDetailViewModelPlus)
    case itemManaColdownItem(manacd: ItemDetailViewModelPlus)
    case itemNotesItem(notes: ItemDetailViewModelPlus)
    case itemAttribItem(attrib: ItemDetailViewModelPlus)
    case itemLoreItem(lore: ItemDetailViewModelPlus)
    case itemComponentsItem(components: ItemDetailViewModelPlus)
}

enum ItemDetailTableViewSection {
    case infoSection(items: [ItemDetailTableViewItem])
    case hintSection(items: [ItemDetailTableViewItem])
    case manacdSection(items: [ItemDetailTableViewItem])
    case notesSection(items: [ItemDetailTableViewItem])
    case attribSection(items: [ItemDetailTableViewItem])
    case loreSection(items: [ItemDetailTableViewItem])
    case componentsSection(items: [ItemDetailTableViewItem])
}

extension ItemDetailTableViewSection: SectionModelType {
    typealias Item = ItemDetailTableViewItem
    
    var items: [ItemDetailTableViewItem] {
        switch self {
        case .infoSection(items: let items):
            return items
        case .hintSection(items: let items):
            return items
        case .manacdSection(items: let items):
            return items
        case .notesSection(items: let items):
            return items
        case .attribSection(items: let items):
            return items
        case .loreSection(items: let items):
            return items
        case .componentsSection(items: let items):
            return items
        }
    }
    
    init(original: ItemDetailTableViewSection, items: [Self.Item]) {
        self = original
    }
}

I have DataSource like this:

struct ItemDetailDataSource {
    typealias DataSource = RxTableViewSectionedReloadDataSource
    
    static func dataSource() -> DataSource<ItemDetailTableViewSection> {
        return .init { (dataSource, tableView, indexPath, item) -> UITableViewCell in
            
            switch dataSource[indexPath] {
            case .itemInfoTopItem(let info):
            case .itemHintItem(let hint):
            case .itemManaColdownItem(let manacd):
            case .itemNotesItem(let notes):
            case.itemAttribItem(let attrib):
            case .itemLoreItem(let lore):
            case .itemComponentsItem(let components):
                guard let cell = tableView
                        .dequeueReusableCell(withIdentifier: ConstantsForCell.itemComponentTableViewCell,
                                                               for: indexPath)
                        as? ItemComponentTableViewCell else {
                    return UITableViewCell()
                }
                cell.registerCell()
                cell.configure(components)
                return cell
            }
        }
    }
}

At components case I have 1 cell, in this cell I create CollectionView:

class ItemComponentTableViewCell: UITableViewCell {
    @IBOutlet weak var itemComponentCollectionView: UICollectionView!
    
    var components = BehaviorSubject<[String]>(value: [])
    let disposeBag = DisposeBag()
    
    override func awakeFromNib() {
        super.awakeFromNib()
        
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
    
    func registerCell() {
        itemComponentCollectionView.register(UINib(nibName: "ComponentCollectionViewCell",
                                                   bundle: nil),
                                             forCellWithReuseIdentifier: "ComponentCollectionViewCell")
    }
    
    func configure(_ viewModel: ItemDetailViewModelPlus) {
        components.onNext(viewModel.components)
        components
            .bind(to: itemComponentCollectionView
                    .rx
                    .items(cellIdentifier: "ComponentCollectionViewCell",
                           cellType: ComponentCollectionViewCell.self)) { _, element, cell in
                cell.configure(element)
            }
            .disposed(by: disposeBag)
    }
}

I received an error like this: "Assertion failed: This is a feature to warn you that there is already a delegate (or data source) set somewhere previously. The action you are trying to perform will clear that delegate (data source) and that means that some of your features that depend on that delegate (data source) being set will likely stop working."

I tried to fix it by setting for collectionView datasource = nil and delegate = nil but it has an error again "Proxy changed from the time it was first set."

Can anyone help me? Thank all. Sorry for my bad English

Cells get reused. You need to unbind the previous use of the cell before binding the new use. This can do it:

class ItemComponentTableViewCell: UITableViewCell {
    @IBOutlet weak var itemComponentCollectionView: UICollectionView!
    
    var components = BehaviorSubject<[String]>(value: [])
    var disposeBag = DisposeBag()

    override func prepareForReuse() {
        super.prepareForReuse()
        disposeBag = DisposeBag()
    }

    // other methods as necessary.
}   

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM