NSTableViewDiffableDataSourceを使う時に気をつけること
一つ以上カラムがないと何も出ない
Interface Builder を使うなら大丈夫そうだが、コードで作ると初期状態ではカラムが何もない
カラムが何もないと何も表示されないため、適当に足しておく必要がある
code:swift
tableView.addTableColumn(.init())
初期状態の dataSource から snapshot を作ってはいけない
永遠にappendしていくデータとかの時に、適当に初期化時にこういうコードを書いちゃうと思う
code:swift
var snapshot = dataSource.snapshot()
snapshot.appendSections(.main) dataSource.apply(snapshot)
しかし NSTableViewDiffableDataSource で一回目の apply の前に snapshot を作って apply すると
Invalid parameter not satisfying: identifiers で怒られる
なんで??
対処方法としては普通に NSDiffableDataSourceSnapshot<Section, Item> を作ってapplyすればよい
code:swift
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections(.main) dataSource.apply(snapshot)
ところで NSDiffableDataSourceSnapshot って長いのを毎回書いてさらに Section と Item の型名も書かないといけないの長すぎるので dataSource 側に plainSnapshot() とか型エイリアスとか何かしらほしい。。。
delegate を作って tableView(_:viewFor:row:) のstub実装を用意しないとviewが出ない
が、NSTableViewDiffableDataSource は cellProvider を受け取るぞ!
どうなってるんだ?
cellProvider
A closure that creates and returns each of the cells for the table view from the data the diffable data source provides. This replaces the tableView(_:viewFor:row:) delegate method.
つまり delegate の tableView(_:viewFor:row:) を勝手に置き換えてくるらしい
仕組みがよくわからない
普通に呼ぶとちゃんと自前実装のほうが呼ばれるが AppKit によって呼ばれる時は cellProvider のほうが呼ばれる
もしかして delegateのtableView(_:viewFor:row:) があるかどうかで view-based かどうかを決めている?
本当は実際にviewを出す時には diffable data source を検出してよしなにする?
view-based かどうかの決定のためにないと死ぬ説
適当にこういうコードをdelegateに書いて検証してみる
code:swift
override func responds(to aSelector: Selector!) -> Bool {
return true
}
return super.responds(to: aSelector)
}
結果通ったのでやっぱり view-based かどうかの決定に必要なだけっぽそう
usesAutomaticRowHeights=true なのに automatic に row の height を計算してくれない
正確にはアニメーション付きapplyするときだけ
のでアニメーションなしapplyすればよい!
と思うでしょ?アニメーションなしapplyは内部的に reloadData()を呼ぶのでよろしくない
解決方法募集中