SwiftBondでTableViewのanimationを消す


# はじめに
[SwiftBond](https://github.com/SwiftBond/Bond)

以前はできなかった、UITableViewのデータが変わったときのアニメーションの変更が、v4.0.2でできるようになりました。
この記事ではそのやり方を簡単に解説しています。

ちなみにUICollectionViewはまだ未対応で、PRもでていません。

この記事は2015-10-24時点の情報です。

## やり方

`BNDTableViewProxyDataSource` を継承したクラスを作成し、アニメーションの設定を行うメソッドを実装して、このクラスのインスタンスをtableViewのdataSourceのbind時に渡すだけです。

#### 1. `BNDTableViewProxyDataSource` を継承したクラスの作成

```
class ABCTableViewProxyDataSource : BNDTableViewProxyDataSource {
    @objc func tableView(tableView: UITableView, animationForRowAtIndexPaths indexPaths: [NSIndexPath]) -> UITableViewRowAnimation {
        return .None
    }
    
    @objc func tableView(tableView: UITableView, animationForRowInSections sections: Set<Int>) -> UITableViewRowAnimation {
        return .None
    }
}
```

#### 2. bindToする際に`proxyDataSource`に先ほどのクラスのインスタンスを渡す

```swift:ViewControllerでのbind
class ABCTableViewController {

    ...
    
    // アニメーションが必要な際に都度参照されるので、こんな感じで保持しておく
    let proxy = ABCTableViewProxyDataSource()
    
    ...
    
    override func viewDidLoad() {
        
        dataSource.bindTo(tableView, proxyDataSource:self.proxy) { (indexPath, dataSource, tableView) -> UITableViewCell in
        
            ...
            
            return cell
        }
        
        ...
        
    }

}
```

that's all☆


## 簡単な解説

```swift:bindTo
dataSource.bindTo(tableView) { indexPath, arrays, tableView -> UITableViewCell in

    ...
    
    return cell
}

```

このようにbindしたときに、デフォルトでは`BNDTableViewDataSource` というクラスが呼ばれてあれこれとTableViewのDataSource系のメソッドをよしなにやってくれています。
その中で以下の部分がアニメーションの設定がなされている部分です。


```swift:BNDTableViewDataSourceのアニメーションの設定箇所
...
  private class func applySectionUnitChangeSet(changeSet: ObservableArrayEventChangeSet, tableView: UITableView, dataSource: BNDTableViewProxyDataSource?) {
    switch changeSet {
    case .Inserts(let indices):
      tableView.insertSections(NSIndexSet(set: indices), withRowAnimation: dataSource?.tableView?(tableView, animationForRowInSections: indices) ?? .Automatic)
    case .Updates(let indices):
      tableView.reloadSections(NSIndexSet(set: indices), withRowAnimation: dataSource?.tableView?(tableView, animationForRowInSections: indices) ?? .Automatic)
    case .Deletes(let indices):
      tableView.deleteSections(NSIndexSet(set: indices), withRowAnimation: dataSource?.tableView?(tableView, animationForRowInSections: indices) ?? .Automatic)
    }
  }
  
  private class func applyRowUnitChangeSet(changeSet: ObservableArrayEventChangeSet, tableView: UITableView, sectionIndex: Int, dataSource: BNDTableViewProxyDataSource?) {
    switch changeSet {
    case .Inserts(let indices):
      let indexPaths = indices.map { NSIndexPath(forItem: $0, inSection: sectionIndex) }
      tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: dataSource?.tableView?(tableView, animationForRowAtIndexPaths: indexPaths) ?? .Automatic)
    case .Updates(let indices):
      let indexPaths = indices.map { NSIndexPath(forItem: $0, inSection: sectionIndex) }
      tableView.reloadRowsAtIndexPaths(indexPaths, withRowAnimation: dataSource?.tableView?(tableView, animationForRowAtIndexPaths: indexPaths) ?? .Automatic)
    case .Deletes(let indices):
      let indexPaths = indices.map { NSIndexPath(forItem: $0, inSection: sectionIndex) }
      tableView.deleteRowsAtIndexPaths(indexPaths, withRowAnimation: dataSource?.tableView?(tableView, animationForRowAtIndexPaths: indexPaths) ?? .Automatic)
    }
  }
...
 
```

ようはdataSourceがnilでなく、指定されているメソッドが実装されていたら、それを実行、でなければデフォルトの値を返す、ということを行っています。

ここで使われている`dataSource`という変数はbindTo時の、`proxyDataSource`という引数で渡されてくるものが入ってきています。
さらに`proxyDataSource`は、`BNDTableViewProxyDataSource`に準じていて、`BNDTableViewProxyDataSource`に以下のようにアニメーションの設定を返すメソッドが定められています。

```swift:BNDTableViewProxyDataSourceの該当メソッド
@objc public protocol BNDTableViewProxyDataSource {
  /// Override to specify custom row animation when row is being inserted, deleted or updated
  optional func tableView(tableView: UITableView, animationForRowAtIndexPaths indexPaths: [NSIndexPath]) -> UITableViewRowAnimation
  
  /// Override to specify custom row animation when section is being inserted, deleted or updated
  optional func tableView(tableView: UITableView, animationForRowInSections sections: Set<Int>) -> UITableViewRowAnimation
}
```
そんなわけで、proxyDataSourceで渡す変数のクラスに、上記の2つのメソッドを実装しておけば、アニメーションが変更できるようになるわけです。

メソッドを実行する際に、option引数としてhashを渡して、値があれば内部の処理を変える、といったことをするように、上記のようなクラスを渡して、そのクラスインスタンスにメソッドがあれば実行する、というシンプルな発想です。名前どおり、proxyしてくれています。