ArrayControllerでbindしたNSTableViewでソートの実装

注意事項
ArrayControllerでbindしたNSTableViewでソートの実装を試みた。
また、前回よく分からなくなっていたテーブルの選択行取得についても、理解に進展があったのでメモ。

完成版サンプルプログラム: GitHub - tnbinkttm203582/tableViewSortSample: sample

■ソートの実装

前回、ソートなしのNSTableViewへのinsert位置変更を試みたが、その後ソートあり版を試みて、そもそもソートありならインサート位置なんか関係なくなるという当たり前のことにようやく気付いた。
ということで、ArrayControllerのadd:なりinsert:に素直に接続し、ソートができるようにした。

ArrayControllerを使っている場合、特に目新しいことはする必要がなく、NSTableColumn の Bindings Inspector > Value の 「Creates Sort Descriptor」にチェックを入れればいい。

f:id:nashikachi:20160408200058j:plain:w450

これでヘッダ部分をクリックすればソートできる。
f:id:nashikachi:20160408201131j:plain:w260
f:id:nashikachi:20160408201133j:plain:w260

※ないと思うが、一応補足。
何故か前回に続き、またも↓の不要なバインディングにチェックが入っていてソートができなかった...。チェックが入った原因は追わないが、もしソートできなければ念のため確認してみるといいかもしれない。
f:id:nashikachi:20160408210913p:plain:w430

■選択行のインデックス取得

ソートをするのならインサート位置も関係なくなるので、選択行の位置を取得する必要もなくなる。だからArrayControllerのadd:、remove:に直接接続すればいい...というわけでもない。例え直接テーブルデータに手を加えなくても、選択位置を取得し、それを元に別のデータをいじることもある。
前回では、行番号を取得するのに TableView の selectedRowメソッド を使っていた。しかしソートをすると、selectedRow:で示される行番号はArrayControllerのインデックスと一致しなくなる場合がある。というか、恐らくArrayControllerでbindしている場合、テーブルデータに対する全てのデータはArrayController経由で行うべきなんだろう。以前はその辺を理解していなかった。

ArrayControllerでbindしているTableViewで選択されている行の情報を取得する場合、ArrayControllerに対して selectedObjects: や selectionIndexes: を呼ぶ。

以下は、削除する際に、削除するオブジェクトとそのインデックスを取得するサンプル。

ArrayControllerの_arrConに対して、selectedObjects: や selectionIndexes: で選択行の情報を取得している。(今回は複数行選択可としている)
この方法なら、selectedRow:と違い、ソートしても選択行とデータが一致する。

■まとめ

・ArrayControllerを利用すればソートも楽に実装できる。
・選択行の情報を取得するのは、TableViewに対しててではなく、ArrayControllerに対して行う。