RxSwift: Как заполнить данные в ячейке представления коллекции внутри представления таблицы, используя ViewModel? - PullRequest
1 голос
/ 18 апреля 2020

У меня есть следующая структура:

- TableView
-- Custom Table View Cell
--- CollectionView
---- Custom CollectionView Cell

Я хочу понять, как я могу передать данные из / с использованием модели представления в этой структуре с помощью RxSwift - Структура MVVM.

Всякий раз, когда Я получаю ответ от API, он должен обновить данные в строках табличного представления и соответствующей ячейке представления коллекции соответственно.

Ответы [ 2 ]

1 голос
/ 19 апреля 2020

Самое простое решение - использовать массив массивов.

Например. Давайте предположим, что ваш API возвращает:

struct Group: Decodable {
    let items: [String]
}

Тогда ваша модель представления будет такой простой:

func tableViewItems(source: Observable<[Group]>) -> Observable<[[String]]> {
    return source
        .map { $0.map { $0.items } }
}

При создании вашей ячейки вы можете заключить внутренний массив в наблюдаемый с помощью 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)
1 голос
/ 18 апреля 2020

Вот пример, который я только что написал, чтобы продемонстрировать, как вы можете использовать RxSwift, чтобы делать то, что вы хотите. Важное примечание: Это грубый пример, неоптимально написанный и не проверенный! Я только что написал это с помощью текстового редактора, надеюсь, он вам поможет, если нет, то я попытаюсь полировать sh, когда у меня будет больше времени.

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())
    }
}
...