個人的には、以下が最もクリーンな解決策だと思います。
- 配列内のアイテムのモデルを作成します。
- UITableViewCellサブクラスを作成して、セルにモデルを表示します。サブクラスには、モデルを受け入れ、モデルが変更されたときにそれ自体を再描画するプロパティがあります。
ニュースアプリがあるとしましょう。配列には、モデルNewsItemを作成するためのアイテムが含まれています。モデルヘッダーは次のようになります。
NewsItem.h
@interface FSNewsItem : NSObject <NSCoding>
@property (nonatomic, copy, readonly) NSString *title;
@property (nonatomic, copy, readonly) NSURL *URL;
@property (nonatomic, copy, readonly) NSString *time;
@property (nonatomic, copy, readonly) NSString *points;
@property (nonatomic, copy, readonly) NSString *author;
// initialiser
+ (FSNewsItem *)newsItemWithTitleNode:(HTMLNode *)node
subTextNode:(HTMLNode *)subNode;
@end
次に、セルに対してNewsItemCellを作成します。NewsItemCellのコードは次のようになります。
NewsItemCell.h
@interface FSNewsItemCell : UITableViewCell
@property (nonatomic, strong) FSNewsItem *newsItem;
@end
NewsItemCell.m
@interface FSNewsCell ()
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *detailLabel;
@end
@implementation FSNewsItemCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
self.titleLabel = [[UILabel alloc] init];
[self addSubview:_titleLabel];
self.detailLabel = [[UILabel alloc] init];
[self addSubview:_detailLabel];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
const CGRect bounds = self.bounds;
CGFloat width = bounds.size.width - (FS_FLOAT_PADDING * 2) - 15.0f;
_titleLabel.frame = CGRectMake(FS_FLOAT_PADDING, FS_FLOAT_CELL_PADDING_VERTICAL, width, 20.0f);
CGFloat y = _titleLabel.frame.size.height + (FS_FLOAT_CELL_PADDING_VERTICAL * 2);
_detailLabel.frame = CGRectMake(FS_FLOAT_PADDING, y, width, 15.0f);
}
#pragma mark - Private
- (void)setNewsItem:(FSNewsItem *)newsItem
{
if (_newsItem == newsItem)
{
return;
}
_newsItem = newsItem;
self.titleLabel.text = newsItem.title;
if (_newsItem.points && _newsItem.time)
{
self.detailLabel.text = [NSString stringWithFormat:@"%@ | %@", _newsItem.points, newsItem.time];
}
else
{
self.detailLabel.text = newsItem.time;
}
[self setNeedsLayout];
}
最後に、セルにニュースアイテムを表示する場合、コードは次のようになります。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
FSNewsItemCell *cell = (FSNewsItemCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[FSNewsItemCell alloc] initWithStyle:UITableViewCellStylePlain reuseIdentifier:CellIdentifier];
}
cell.newsItem = [_items objectAtIndex:indexPath.row];
return cell;
}
これは私の意見では、最もクリーンなソリューションであり、私がほとんどの場合採用しているアプローチです。ビューコントローラを小さく保つのが好きです。また、ビューコントローラーが(カスタム)テーブルビューセルのコントロールを知る必要がないという事実も気に入っています。テーブルビューセルは、提供されたデータに応じて、それ自体を描画する方法について全責任を負います。