例えばこんな感じ。
- (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]