Storyboardを使ってUITableViewのある画面を作り、そのCellを複数画面で使いまわすためにxibとして作成するときのTipsです。
UITableViewにiOS5から追加されたregisterNib:forCellReuseIdentifier:メソッドを使うことで、作成したxibをUITableViewに登録することができ、nilチェックとloadNibを必要としないシンプルなコードにすることができます。
コードで例を示すために使いまわしたいCellを"SampleTableViewCell"とします。作成するのは3つ
- SampleTableViewCell.xib
- SampleTableViewCell.h
- SampleTableViewCell.m
ここで説明するregisterNib:forCellReuseIdentifier:メソッドは、UITableViewを保持するUITableViewControllerのviewDidLoadなどで呼び出します。これによってCell用に作成したxibファイルがUITableViewに登録されます。
- (void)viewDidLoad
{
[super viewDidLoad];
UINib *nib = [UINib nibWithNibName:@"SampleTableViewCell" bundle:nil];
[self.tableView registerNib:nib forCellReuseIdentifier:@"Cell"];
}
あとはStoryboardでStaticやDynamicなCellを呼び出す時と同じように次のようにします。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
SampleTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
return cell;
}
これで下記のようにcellの再利用をnilチェックし生成する必要はありません。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
SampleTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
// こういう処理は必要なくなるよと
cell = [SampleTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Configure the cell...
return cell;
}
なぜ再利用のチェックと生成を行う必要がないかというと、先ほどの説明通りにnibを登録してればnilを返すことがないからです。これについてはAppleのUITableViewのリファレンスでdequeueReusableCellWithIdentifier:がnilを返す場合について下記のように言及されていましたので参考になります
- 再利用されるcellが存在しない時
- nibが登録されていない時(iOS5から)
- Classが登録されていない時(iOS5から)
つまり、nilが返るという状態は実装ミスです。実装ミスがすぐに発覚するので良いつくりといえるでしょう。
したがって、先述のメソッドによりCellが登録されることで内部キューになければ自動で生成を行なってくれるため、Cellの再利用チェックと生成のコードが必要ないわけです。余談ですがStoryboardのCellを使うようになってから再利用チェックを書く必要がなくなっていたのはStoryboardが登録の手続きを行なっていたからなんですね。
これらは当然、Storyboard+xibの時にかぎらず、UITableViewでさえあれば使えます。また、registerClass:forCellReuseIdentifier:によりクラスを指定できるためxibである必要も有りません。