RxSwift. Что использовать для Observable ‹Void›?

Написание проекта на MVVM и попытка связать все с помощью RxSwift. К сожалению, мне не удалось найти правильный способ привязки действий.

Например, у меня есть таблица и простые ячейки с одной кнопкой - «Выбрать».

Для этого у меня будет две модели просмотра: ListViewModel & CellViewModel

ListViewModel будет создавать массив из CellViewModel, и ему нужно будет подписаться на событие выбора (настраиваемое событие).

Сейчас я использую для этих целей BehaviorSubject, но это выглядит некрасиво. Кто может указать мне, как это нужно реализовать с помощью RxSwift?

class CellViewModel {

    private let selectionSubject = BehaviorSubject<Void>(value: ())

    // Will be used by ListViewModel
    var selectionObservable: Observable<Void> {
        return selectionSubject.asObservable()
    }

    func subscribeOnSelection(_ observable: Observable<Void>, disposeBag: DisposeBag) {
        observable
            .bind(to: selectionSubject)
            .disposed(by: disposeBag)
    }

    private func autoSelect() {
        selectionSubject.on(next: ())
    }
}

class Cell: UITableViewCell {
    @IBOutlet private var selectionButton: UIButton!

    private let disposeBag = DisposeBag()

    func bind(to viewModel: CellViewModel) {
        viewModel.subscribeOnSelection(selectionButton.rx.tap.asObservable(), disposeBag: disposeBag)
    }
}

person Vasyl Khmil    schedule 30.04.2019    source источник


Ответы (1)


Вам где-то нужна тема, потому что эмиттер события не существует, когда создается потребитель события. Обычно я помещаю один объект в контроллер представления, а не объект в каждую ячейку. Что-то вроде этого:

class Cell: UITableViewCell {
    @IBOutlet private var selectionButton: UIButton!

    private var disposeBag = DisposeBag()

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

    func configure(with makeViewModel: (Observable<Void>, DisposeBag) -> Void) {
        makeViewModel(selectionButton.rx.tap.asObservable(), disposeBag)
    }
}

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

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    let disposeBag = DisposeBag()

    var makeViewModel: (Observable<CellID>) -> Observable<[CellID]> = { _ in fatalError() }

    override func viewDidLoad() {
        super.viewDidLoad()

        let cellSelection = PublishSubject<CellID>()

        let cells = makeViewModel(cellSelection)

        cells
            .bind(to: tableView.rx.items(cellIdentifier: "Cell", cellType: Cell.self)) { index, element, cell in
                cell.configure(with: { selected, disposeBag in
                    selected
                        .map { element }
                        .bind(to: cellSelection)
                        .disposed(by: disposeBag)

                })
                return
            }
            .disposed(by: disposeBag)
    }
}
person Daniel T.    schedule 30.04.2019