2017年04月10日

[Mac,Swift2]NSTableViewでソートする

NSTableViewで列を指定して並べ替える方法は、Objective-Cでは簡単に実装することができた。NSArray/NSMutableArrayがNSSortDescriptorを使うメソッドを以て致し、NSArrayが保持しているオブジェクトがNSObjectを親クラスに持っていればkey-value対応により適切に応答してくれた。Mac/iOSのObjective-Cでは全てのオブジェクトはNSObjectを親クラスに持つ。

例えばこんな感じ。


- (void)tableView:(NSTableView *) aTableView
sortDescriptorsDidChange:(NSArray *) oldDescriptors
{
[mainList sortUsingDescriptors:[mainListView sortDescriptors]];
[mainListView reloadData];
}


※ここでは以下のようなインスタンス変数の宣言がされているとする。

IBOutlet NSTableView *mainListView;
NSMutableArray *mainList;


ところが、Swiftの配列はNSSortDescriptorを引数に持つメソッドがない。ということは自分で実装しなければならない。

もちろん、NSTableViewで表示するデータをNSArrayで持てば問題はないのだろうが、他のところでは配列オブジェクトを使っていてここだけNSArrayにするのはなんだか整合していないようで、気持ちが悪い。

そこで配列オブジェクトを使っている場合にNSTableViewでソートする場合の方法を試行錯誤してみた。

なお、ここでは以下のような定義を前提にしている。

class MyClass {
let uid: Int
let name: String
}
let array : [MyClass]


NSSortDescriptorは、以下の変数を持つ。

var key:​ String?
var ascending:​ Bool
var selector:​ Selector?


keyという項目で、ascendingが真なら昇順、偽なら降順に並べ替える。判定に用いるメソッドとしてはselectorを使う。ただし、今回は比較関数を定義するのが面倒なので使っていない。


func tableView(tableView: NSTableView,
sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor])
{
array.sortInPlace { (left, right) -> Bool in
for desc in tableView.sortDescriptors {
if desc.key == "uid" {
if left.uid < right.uid {
return desc.ascending
} else if left.uid > right.uid {
return !desc.ascending
}
} else if desc.key == "name" {
if left.name < right.name {
return desc.ascending
} else if left.name > right.name {
return !desc.ascending
}
}
}
return false
}
tableView.reloadData()
}



配列が変更可能な場合にはsortInPlace()、変更不可の場合にはsort()を使う。ソート可能なNSTableViewのデータは通常変更可能な配列変数に入れるので、sortInPlace()を使うことになるはず。


mutating func sortInPlace(@noescape _ isOrderedBefore:
(Self.Generator.Element, Self.Generator.Element) -> Bool)



@warn_unused_result(mutable_variant="sortInPlace") func sort(@noescape _ isOrderedBefore:
(Self.Generator.Element, Self.Generator.Element) -> Bool) -> [Self.Generator.Element]

posted by 永遠製作所 at 00:58| 東京 ☁| Comment(0) | TrackBack(0) | Swift | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック