LoginSignup
13
14

More than 5 years have passed since last update.

SwiftBondでTableViewのanimationを消す

Last updated at Posted at 2015-10-24

はじめに

SwiftBond

以前はできなかった、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に先ほどのクラスのインスタンスを渡す

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☆

簡単な解説

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

    ...

    return cell
}

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

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に以下のようにアニメーションの設定を返すメソッドが定められています。

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してくれています。

13
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14