ページ

2009年11月26日木曜日

Cocoaの日々: NSTableView にカスタムビューを表示する(3) カスタムセルの作成

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: NSTableView にカスタムビューを表示する(2) ひな形作成〜Cocoa Bindings

今回は NSCell のサブクラスを作り、それを NSTableView へ表示してみよう。

ビュー

新規にウィンドウを用意しそこへ NSTableView を貼付ける。前回のものは比較の為に残しておく。



NSTableView の delegate として TableViewController を指定しておく。


カスタムセル

NSCell のサブクラスを用意する。

CustomCell.h

@interface CustomCell : NSCell {

}

@end


試しに drawWithFrame:inView: をオーバーライドして、緑色で塗りつぶすコードを書いてみた。

CustomCell.m

@implementation CustomCell

- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
[[NSColor greenColor] set];
NSRectFill(cellFrame);
}
@end



NSTableViewDelegate

NSTableViewDelegate のうち -tableView:dataCellForTableColumn:row: を実装した。

TableViewController.m

- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
NSLog(@"tableView: %@", tableView);
NSLog(@"  tableColumn: %@", tableColumn);
NSLog(@"  row: %d", row);


CustomCell* cell = [[[CustomCell alloc] init] autorelease];
return cell;
}

呼び出し状況がわかるように NSLog を入れておいた。


実行



出た。

デバッガコンソールを見ていると -[NSTableViewDelegate tableView:dataCellForTableColumn:row:] は頻繁に呼び出されている。


NSTableView をスクロールするとこれから表示されようとする行(row)で呼び出されるし、マウスカーソルを上に載せても呼び出される。また tableColumn が null だった。


考察

今回は -[NSTableViewDelegate tableView:dataCellForTableColumn:row:] の呼び出し毎に NSCell を生成して返していた。何度も呼び出される事を考えると使い捨てではなく、あらかじめ NSCellをプールしておいて再利用する方が良いかもしれない。そういえば iPhone の UITableViewCell は再利用を前提とした作りになっていたっけ。ただ UITableViewCell は UIView のサブクラスなので、NSViewよりも軽い NSCellの場合はそこまで考えなくてもよいかもしれない。


なお NSCell のサブクラス化については Mac Dev Center に指針がある。
Mac Dev Center: Control and Cell Programming Topics for Cocoa: Subclassing NSCell


必要なら初期化メソッド(-initImageCell など)のオーバーライドすることやその他Target-Action、マウストッキング、描画を行う際にオーバライドすべきメソッドが紹介されている。また最後に copyWithZone: についての説明もあった。
If the subclass contains instance variables that hold pointers to objects, consider overriding copyWithZone: to duplicate the objects. The default version copies only pointers to the objects.
NSCell は複製されて使われることが多いということか。今後の実装で copyWithZone: を考慮することは覚えておこう。そういえば ADCのサンプル SourceView でもカスタムセルは copyWithZone: を実装していたっけ。


ソースコード

github からどうぞ。
CustomCell at 20091126 from xcatsan's SampleCode - GitHub

参考

NSTableView with custom cells - Stack Overflow