【问题标题】:Binding to a UIRefreshControl after network call网络调用后绑定到 UIRefreshControl
【发布时间】:2016-07-21 08:46:14
【问题描述】:

我是 RxSwift 的新手,我想知道如何能够“被动地”将 UIRefreshControl 与 UITableView 一起使用,而不是创建目标的常规方式,并手动调用 beginRefreshing()endRefreshing()

例如,假设我正在从 API 加载一些字符串:

class TableViewController: UITableViewController {

    var data : [String] = []

    let db = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        refreshControl = UIRefreshControl()

        //I don't want to use
        //refreshControl?.addTarget(self, action: #selector(getData), forControlEvents: .ValueChanged)

        //Do something to refreshControl.rx_refreshing?
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
        let str = data[indexPath.row]
        cell.textLabel?.text = str
        return cell
    }

    //MARK: - Requests

    private func getData() {
        let myData = MyAPI.getData() //Returns Observable<[String]>
        myData
            .subscribe({ [weak self] (event) in
                switch event {
                case .Next(let strings):
                    self?.data = strings
                    self?.tableView.reloadData()
                    break
                case .Error(let err):
                    print(err)
                    break
                case .Completed:
                    break
                }
                // self?.refreshControl?.endRefreshing()
                })
            .addDisposableTo(db)
    }
}

MyAPI 发送一些字符串值的请求,我如何绑定refreshControl 以调用getData() 并在完成(或出错)网络请求时停止刷新?需要绑定refreshControl.rx_refreshing吗?

【问题讨论】:

    标签: ios swift uirefreshcontrol rx-swift


    【解决方案1】:

    RxSwift 的示例应用程序提供了一个有趣的类来处理这种逻辑:ActivityIndicator

    一旦你加入了ActivityIndicator,将rx_refreshing绑定到请求的代码就变得非常简单了。

    let activityIndicator = ActivityIndicator()
    
    override func viewDidLoad() {
      super.viewDidLoad()
    
      refreshControl = UIRefreshControl()
    
      // When refresh control emits .ValueChanged, start fetching data
      refreshControl.rx_controlEvent(.ValueChanged)
        .flatMapLatest { [unowned self] _ in
          return self.getData()
          .trackActivity(activityIndicator)
        }
        .subscribeNext { [unowned self] strings in
          self.data = strings
          self.tableView.reloadData()
        }
        .addDisposableTo(db)
    
      // Bind activity indicator true/false to rx_refreshing
      activityIndicator.asObservable()
        .bindTo(refreshControl.rx_refreshing)
        .addDisposableTo(db)
    }
    
    // getData only needs to return an observable, subscription is handled in viewDidLoad
    private func getData() -> Observable<[String]> {
      return myData = MyAPI.getData() //Returns Observable<[String]>
    }
    

    【讨论】:

    • 非常感谢!当我尝试它时,我不得不将activityIndicator.asDriver() 更改为activityIndicator.asObservable(),否则它会给出Value of type Driver&lt;Bool&gt; has no member bindTo。另外,如何以编程方式将控件事件推送到 refreshControl?我试过refreshControl.beginRefreshing(),但这不起作用。
    • 您想通过编程方式发送事件来达到什么目的?如果您希望在执行viewDidLoad 时执行第一个getData(),最好在.flatMapLatest 之前使用.startWith()。我已更新答案以使用.asObservable()
    • 是的,我就是这个意思。这个 Rx 的东西还是新的。非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-06
    相关资源
    最近更新 更多