2007年11月15日木曜日

NSArrayController(NSTableView)の選択結果の取得について

追記 2008/1/7
SelectedRowInTableView
・各TableColumnだけでなくTableViewのContentまでバインディングしていたのをやめるように修正.
・これによりカラムヘッダーをクリックしてそのカラムでソートされるようになった.
・また選択結果をNSLogで書き出していたがNSTextViewを用意してそこに書き出すように修正.
http://y30.net/pg/cocoa_prj/SelectedRowInTableView.zip



プロジェクトを用意してみた.
SelectedRowInTableView
10.5で作成.(一応Xcode 2.4互換プロジェクトで buildが10.4 Universalと設定.IBも10.4以上互換…だめなら連絡ください.)
KVOで観測してNSArrayControllerのselectionIndexesで値を取得する例.
http://y30.net/pg/cocoa_prj/SelectedRowInTableView.zip


関連:この記事は以下の2つのエントリーのまとめ.
KVO : で,テーブルの行選択するたびに知りたい!のでKVO.
http://edotprintstacktrace.blogspot.com/2007/07/kvo-kvo.html
KVC : で,テーブルの行選択の内容を調べたい
http://edotprintstacktrace.blogspot.com/2007/07/kvc.html



前提:
NSTableViewとNSArrayControllerを用意
NSTableView側のBindingにて"Table Coontent"中の"content"と"selectionIndexes"のBindを設定.
"content"はBind toとしてNSArrayController, Controller KeyとしてarrangedObjectsを設定,
"selectionIndexes"はBind toとしてNSArrayController, Controller KeyとしてselectionIndexesを設定します.




NSArrayControllerを用いる場合:
    (NSArrayController *_controller; //IBでつないであるとします.)
int selectedIndex= [_controller selectionIndex]; //ひとつだけなら
NSIndexSet *indexSet= [_controller selectionIndexes]; //複数選択なら

任意のタイミングで呼べば使えます.
#変わったときを知りたい場合は別の2つの方法となる.

でNSIndexSetから選択を取り出す場合.
リンゴの水やり
NSIndexSetから値の取り出し
http://blog.livedoor.jp/gutskun/archives/5865339.html
static void showIndexSet(void)
{
NSIndexSet *indexes = createIndexSet();
int index = [indexes firstIndex];
while(index != NSNotFound) {
NSLog(@"index = %d", index);
index = [indexes indexGreaterThanIndex:index];
}
}




KVCで行く場合(トリッキーかも):
NSArrayControllerのInspectorのbindings中から"Controller Content Parameters"の"selectionIndexes"を選びます.
"bind to"で任意Object(NSObjectのSubClass MyObjectを用意して,Instanceをつくるなど)を指定し,
"Model Key Path"に任意のキー値(下記例では"foo")を設定する.
Tableで選択が起きるたびにsetFooが呼ばれます.
NSIndexSet *_boo;
- (NSIndexSet *)foo {
return boo;
}
- (void)setFoo:(id)obj {
boo= obj;
}

#fooで戻す値も管理しないといけなくなるので不便かも.

もっと言えばこれでも良い.
NSIndexSet *_foo;

TableViewでの選択の変化は常にfooに入っている.(foo,setFooというメソッドが無い事)



KVOでやってみる場合:
NSArrayControllerを用いる場合と同じ.
ただこれだと変化があった時に呼ばれる.(便利)
-( void )awakeFromNib {
//init中だと_controllerがまだnilです.例えばawakeFromNibなら大丈夫.
[_controller addObserver:self
forKeyPath:@"selectionIndexes"
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context:_controller];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if ([keyPath isEqualToString:@"selectionIndexes"]
&& [object isEqual:_controller]) {
NSIndexSet *indexSet= [_controller selectionIndexes];
}
}


だれかのお役にたったら幸いです.
#間違いあればご指摘いただけると幸いです.

2 件のコメント:

匿名 さんのコメント...

サンプルのプロジェクトがダウンロードできたりすると,いいですね。HMDTみたいに

p_g_ さんのコメント...

ただいま勉強中 さん:
コメントありがとうございます.

プロジェクトですか…確かにIBでの設定などを
言葉で伝えるには無理がありますね.

そのうち対応できたら置いてみますね.