从 catchError 处理后如何恢复数据源

How to recovery dataSource after disposed from a catchError

我有一个 UITableView 由使用 RxSwift 的反应式视图模型填充,分页和刷新运行良好。 viewModel.dataSource() 正在消耗我的 API,有时我会收到一个解析为错误类型的空结果。

我想捕获这个错误并创建一个空状态,隐藏 tableview 并显示一个 emptyViewState。我以为我可以用 catchError 做到这一点。

我的问题是在 catchError 之后,dataSource 被处理了,我无法恢复空状态并重新填充 tableview,我试图重新创建 dataSource 调用 self.bindDataSource() 但我变得致命错误。

有没有办法避免 dataSource 被释放?如何重新连接/重建数据源以从空状态恢复?

class MyViewControl: UIViewController {

    fileprivate let disposeBag = DisposeBag()
    fileprivate let viewModel = ViewModel()
    let dataSource = SearchViewModel.SearchDataSource()

    @IBOutlet fileprivate weak var tableView: UITableView!
    @IBOutlet weak var emptyStateView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // When I disable tableview, can see a hidden view with empty state message and one button
        viewModel.isTableViewHidden
        .bindTo(tableView.rx.isHidden)
        .addDisposableTo(disposeBag)
        self.setupTableView()
    }

    fun setupTableView() {
        // ... setup table view
        self.bindDataSource()
    }
    fileprivate func bindDataSource() {
    // Bind dataSource from search to UITableView
        viewModel.dataSource()
            .debug("[DEBUG] Loading Search Tableview ")
            .bindTo( tableView.rx.items(dataSource: dataSource) )
            .addDisposableTo( disposeBag )
    }

    @IBAction fileprivate func emptyStateAction(_ sender: UIButton) {
        // Do something and try to recreate the bindDataSource
        self.bindDataSource()
    }
}

class SearchViewModel {
    private let disposeBag = DisposeBag()
    typealias SearchDataSource = RxTableViewSectionedReloadDataSource<PaginationStatus<WorkerEntity>>

    let isTableViewHidden = BehaviorSubject<Bool>(value: false)

    // Controls to refresh and paging tableview
    let refreshTrigger  = BehaviorSubject<Void>(value:())
    let nextPageTrigger = PublishSubject<Void>()

    // Others things happing herer

    func dataSource() -> Observable<[PaginationStatus<WorkerEntity>]> {
        return self.refreshTrigger.debug("[DEBUG] Refreshing dataSource")
        .flatMapLatest { [unowned self] _ -> Observable<[PaginationStatus<WorkerEntity>]> in 
            // Access the API and return dataSource
        }
        .catchError { [unowned self] error -> Observable<[PaginationStatus<WorkerEntity>]> in
            // Hidden the tableview
            self.isTableViewHidden.onNext(true)
            // Do others things
            return Observable.of([PaginationStatus.sectionEmpty])
        }
    }
}

当你 bindDataSource() 时,你没有重新初始化你的数据源,所以你将它绑定到一个错误事件。 你需要初始化它,再次绑定它。你可能也想删除你的绑定

让 disposeBagTableView = DisposeBag()

//remove
let dataSource = SearchViewModel.SearchDataSource()


fileprivate func bindDataSource() {
    // Bind dataSource from search to UITableView
        disposeBagTableView = DisposeBag()
        SearchViewModel.SearchDataSource()
            .debug("[DEBUG] Loading Search Tableview ")
            .bindTo( tableView.rx.items(dataSource: dataSource) )
            .addDisposableTo( disposeBagTableView )
    }