使用 RxSwift 刷新后绑定到 UIRefreshControl

Binding to a UIRefreshControl after refresh using RxSwift

我有一个 TableView 的通知。我想使用 UIRefreshControl 通过下拉刷新来刷新。如何使用 rx-swift 做到这一点?这是我的代码。为什么我给变量数据赋值后tableView没有刷新

var refreshControl = UIRefreshControl()
var disposeBag = DisposeBag()

let loadingData = ActivityIndicator()

var data: Observable<[Notification]>!

override func viewDidLoad() {
    super.viewDidLoad()

    self.view = v

    v.tableView.registerClass(NotificationsViewCell.self, forCellReuseIdentifier: "Cell")
    v.tableView.addSubview(refreshControl)
    data = getNotifications()

    configureTableDataSource()
    configureActivityIndicatorsShow()

    refreshControl.rx_controlEvent(.ValueChanged)
        .flatMapLatest{ [unowned self] _ in
            return self.getNotifications()
            .trackActivity(self.loadingData)
        }.subscribe(
            onNext: {notification in
                print("success")
                self.data = Observable.just(notification) // NOT REFRESH TABLEVIEW
            },
            onError: { error in
                print("Error \(error)")
            },
            onCompleted: {() in
                print("complete")
            },
            onDisposed: {() in
                print("disposed")
            })
        .addDisposableTo(disposeBag)
}


func configureTableDataSource(){
    data
        .retry(3)
        .doOnError{ [weak self] error in
            self?.v.emptyLabel.hidden = false
            self?.v.retryButton.hidden = false
        }
        .doOnNext{ [weak self] result in
            if result.count == 0 {
                self?.v.emptyLabel.hidden = false
                self?.v.emptyLabel.text = "Tidak ada bisnis favorit"
            } else {
                self?.v.emptyLabel.hidden = true
                self?.v.retryButton.hidden = true
            }
        }
        .trackActivity(loadingData)
        .retryWhen{ _ in
            self.v.retryButton.rx_tap
        }
        .asDriver(onErrorJustReturn: [])
        .map{ results in
            results.map(NotificationsViewModel.init)
        }
        .drive(v.tableView.rx_itemsWithCellIdentifier("Cell", cellType: NotificationsViewCell.self)) { (index, viewModel, cell) in
            cell.viewModel = viewModel

            let tap = UITapGestureRecognizer(target: self, action: #selector(self.goToProfile(_:)))
            tap.numberOfTapsRequired = 1
            cell.photo.tag = index
            cell.photo.addGestureRecognizer(tap)
        }
        .addDisposableTo(disposeBag)
}

func configureActivityIndicatorsShow(){
    loadingData
        .driveNext{ isLoading in
            if !isLoading {
                self.v.indicatorView.stopAnimating()
            } else {
                self.v.indicatorView.startAnimating()
                self.v.retryButton.hidden = true
                self.v.emptyLabel.hidden = true
            }
        }
        .addDisposableTo(disposeBag)

    loadingData.asObservable()
        .bindTo(refreshControl.rx_refreshing)
        .addDisposableTo(disposeBag)
}

func getNotifications() -> Observable<[Notification]> {
    let parameters = [
        "token": NSUserDefaults.standardUserDefaults().objectForKey("token")! as! String
    ]
    return string(.POST, NOTIFICATION_LIST, parameters: parameters)
        .map { json in
            return Notification.parseJSON(JSON.parse(json)["notifications"])
        }
        .observeOn(MainScheduler.instance)
}

编辑::

var data = Variable<[Notification]>([])

override func viewDidLoad() {
    getNotifications()
        .retry(3)
        .doOnError{ [weak self] error in
            self?.v.emptyLabel.hidden = false
            self?.v.retryButton.hidden = false
        }
        .doOnNext{ [weak self] result in
            if result.count == 0 {
                self?.v.emptyLabel.hidden = false
                self?.v.emptyLabel.text = "Tidak ada notifikasi"
            } else {
                self?.v.emptyLabel.hidden = true
                self?.v.retryButton.hidden = true
            }
        }
        .trackActivity(loadingData)
        .retryWhen{ _ in
            self.v.retryButton.rx_tap
        }
        .bindTo(data)
        .addDisposableTo(disposeBag)


    refreshControl.rx_controlEvent(.ValueChanged)
        .flatMapLatest{ [unowned self] _ in
            return self.getNotifications()
                .doOnError{ [weak self] error in 
                    // This not call after the second pull to refresh if No network connection, so refresh control still appear
                    self?.refreshControl.endRefreshing()  
                }
                .doOnCompleted{ [weak self] result in
                    self?.refreshControl.endRefreshing()
                }
        }.bindTo(data)
        .addDisposableTo(disposeBag)
}

func configureTableDataSource(){
    datas.asObservable()
        .asDriver(onErrorJustReturn: [])
        .map{ results in
            results.map(NotificationsViewModel.init)
        }
        .drive(v.tableView.rx_itemsWithCellIdentifier("Cell", cellType: NotificationsViewCell.self)) { (index, viewModel, cell) in
            cell.viewModel = viewModel
        }
        .addDisposableTo(disposeBag)
}


func configureActivityIndicatorsShow(){
    loadingData
        .driveNext{ isLoading in
            if !isLoading {
                self.v.indicatorView.stopAnimating()
            } else {
                self.v.indicatorView.startAnimating()
                self.v.retryButton.hidden = true
                self.v.emptyLabel.hidden = true
            }
        }
        .addDisposableTo(disposeBag)
}

self.data = Observable.just(notification) 正在创建一个新的 Observable 并在 that Observable 上发送新的 [Notification] 元素,没有人已订阅。

您应该使用 Subject,例如 Variable

// instead of `var data: Observable<[Notification]>!`
let data = Variable<[Notification]>([])

// and then later, when you want to send out a new element:
self.data.value = notification

编辑:向您展示如何将它与您已有的结合使用。

// this will update `data` upon `refreshControl` value change
refreshControl.rx_controlEvent(.ValueChanged)
    .flatMapLatest{ [unowned self] _ in
        return self.getNotifications()
    }
    .bindTo(data)
    .addDisposableTo(disposeBag)

// this will update `loadingData` when `data` gets a new element
data.asDriver().trackActivity(self.loadingData)

// bind to your table view
data.asDriver().drive(//.....

此外,考虑将 retryretryWhen 移动到更早的位置,而不是在您当前拥有它的下游位置(在 table 视图绑定中)。相反,我认为它应该属于 getNotifications.