24/7 twenty-four seven

iOS/OS X application programing topics.

Interface BuilderでカスタムUITableVIewCellを作るときの注意点

Interface Builderを使ってカスタマイズしたUITableViewCellを作る方法(追記あり) - 24/7 twenty-four seven

前に書いた手順は長くて、自分でも見逃しがあったので、よくある間違いをまとめておきます。


XIBファイルのUITableVIewCellを使用するときによくあるトラブルは、だいたい以下の3つだと思います。

  1. 表示されない
  2. スクロール or 前の画面に戻ったときにクラッシュする
  3. 使ってると動作が重くなってくる(=スクロールするたびに消費メモリが増える)

表示されない

ViewControllerのviewプロパティとTableViewCellを接続していないことが原因である場合が多いです。
ViewControllerのインスタンス変数としてTableViewCellを保持して、それと接続するだけでは表示されません。
必ずUIViewControllerがもともと持っているviewプロパティにTableViewCellを接続します。

スクロール or 前の画面に戻ったときにクラッシュする

セルをリリースしているか、デリゲートを解放していないことが考えられます。

セルをリリースしている

セルをリリースしてはいけません。ViewControllerからセルを取り出して、コントローラをリリースします。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	static NSString *identifier = @"FeedListCell";
	FeedListCell *cell = (FeedListCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
	if (cell == nil) {
		FeedListCellController *controller = [[FeedListCellController alloc] initWithNibName:identifier bundle:nil];
		cell = (FeedListCell *)controller.view;
		[controller autorelease];
	}
ViewControllerがリリースされたらクラッシュする

セルにUITextViewなどデリゲートを持つオブジェクトを使用している場合に起こります。
TableViewCellのdeallocメソッドで、デリゲートを解放する処理を書きます。

#import "DiaryCell.h"

@implementation DiaryCell

@synthesize diaryTextView;
@synthesize submitButton;
@synthesize draftButton;

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
	[super setSelected:selected animated:animated];
}

- (void)dealloc {
	[draftButton release];
	[submitButton release];
	[diaryTextView setDelegate:nil];
	[diaryTextView release];
	[super dealloc];
}

@end

以下の部分です。

	[diaryTextView setDelegate:nil];
	[diaryTextView release];

余談ですが、nilを設定するだけで解放されるのは、プロパティで自動生成されるメソッドが以下のようになっているからなので、
自分でsetterを実装した場合などは注意する必要があります。

- (void)setDelegate:(id)aDelegate {
	if (delegate != aDelegate) {
		[delegate release];
		delegate = [aDelegate retain];
	}

使ってると動作が重くなってくる

スクロールを繰り返しているとだんだん引っかかるような動きになったりする場合は、セルの再利用が働いていません。
Xcodeに付属のパフォーマンスツール (Leaks, Object Allocations) で見ると、スクロールするたびにオブジェクトが作られるのが分かると思います。

この場合の原因としては、XIBファイルのTableVIewCellにIdentifierが設定されていないことが考えられます。
UITableViewCellを選択して、「Attributes Inspector(コマンド+1)」を開きます。
TableViewCell>Identifierに任意の名前を設定します。