2016-04-01 7 views
1

私はRxSwiftを初めて使用しています。ターゲットを作成する通常の方法ではなく、UITableViewでUIRefreshControlを「反応的に」使用して手動でとendRefreshing()を呼び出すことができますか? 。例えばネットワークコール後にUIRefreshControlにバインドする

が、私は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は、いくつかの文字列値のための要求を送信し、どのように私は(refreshControlgetData()を呼び出しても、それが終了していますとき、リフレッシュ停止するように結合することができますまたはerror'd)ネットワーク要求? refreshControl.rx_refreshingにバインドする必要はありますか?

答えて

7

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]> 
} 
+0

ありがとうございます!試してみましたが、 'activityIndi​​cator.asDriver()'を 'activityIndi​​cator.asObservable()'に変更しなければなりませんでした。そうでなければ、 'Driver Type of Value 'のメンバーにはbindToがありません。また、制御イベントをプログラムによってrefreshControlにプッシュするにはどうすればよいですか?私は 'refreshControl.beginRefreshing()'しようとしましたが、動作しません。 – jacks205

+0

プログラムでイベントを送信することで何を達成しようとしていますか? 'viewDidLoad'が実行されたときに最初の' getData() 'が実行されるようにするには、' .flatMapLatest'の直前で '.startWith()'を使う方が良いでしょう。私は '.asObservable()'を使う答えを更新しました。 – tomahh

+0

そうです、そういう意味です。まだこのRxものに新しい。助けてくれてありがとう! – jacks205