如何从catchError

时间:2016-11-07 01:58:07

标签: ios swift uitableview rx-swift

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

我想捕获此错误并创建一个空状态,隐藏tableview并显示一个emptyViewState。我以为我可以使用catchError来实现它。

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

有一种方法可以避免处理dataSource吗?如何重新连接/重建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])
        }
    }
}

1 个答案:

答案 0 :(得分:0)

当你使用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 )
    }