結局、本の内容をなぞるだけの状態になっていて、
こんなのEvernoteにやっとけよ状態なのが心に痛い今日この頃です。
と言うわけで、今回読む章は…
6 テーブルのパターン
テーブルは、iPhoneでいちばんよく見かけるユーザーインタフェース。
便利で多機能だが、それゆえに複雑なプログラミングを要求される。
6.1 テーブルとは
6.1.1. テーブルはiPhoneの中心
テーブルビューの特性について書いてある。
6.1.2. UITableView と UITableViewCell
テーブル全体がUITableViewで、各行がUITableViewCell。 *01まあ、名前見れば想像はつく
ポイントは、UITableViewCellが、
Cocoa touchのビューの中では、ちと特殊であるということ。
一般的にCocoa touchのビューはサブクラス化を行わない。
理由は、挙動の制御や拡張はデリゲートで行うという思想から。
ただ、例外的にUITableViewCellは、サブクラス化されることを前提にしている。
6.1.3. テーブルのMVC
テーブルプログラミングのMVC構造について。
ビューがUITableViewとUITableViewCell。
コントローラがUIViewController。
モデルがモデルマネージャ。
ポイントは、UITableViewCellとインスタンスが1対1にならないこと。
理由はメモリの節約。
セルのインスタンスは最小限に抑え、使い回す。
よって、UITableViewCellは直接モデルと結びつけてはならず、
モデルマネージャを介してデータを取得する。
6.2 セルのパターン
6.2.1. 標準のセル
セルは様々にカスタム化して使用する。
その前に、標準のセルスタイル4つと右端に表示するアクセサリを紹介。
6.2.2. contentView と backgroundView
カスタムセルの作成について。
UITableViewCellのサブクラス構造を説明。
目的に応じて、どのサブクラスに手を入れるかを考える。
6.2.3. サブビューの作成
実際に、サブビューをカスタマイズして、RSSチャンネルの情報を表示するビューを作る。
1)UITableViewCellのサブクラスを作る。
名前はRSSCell。
インスタンス変数として宣言し、作成したサブビューへの参照を保持する。
@interface RSSChannelCell : UITableViewCell {
// サブビュー
UILabel* _titleLabel;
UILabel* _feedLabel;
UIImageView* _numberBackgroundImageView;
UILabel* _numberLabel;
}
@end
↓
2)初期化メソッドを実装する。
initWithStyle:reuseIdentifier:を上書き。
その中でサブビューのインスタンス化を行う。
同時にcontentViewにaddSubView:を使ってビュー階層への追加も行う。
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString*)reuseIdentifier {
// 親クラスの初期化メソッドを呼び出し
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if ( !self ) {
return nil;
}
// title ラベルの作成
_titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_titleLabel.font = [UIFont systemFontOfSize:16.0f];
_titleLabel.textColor = [UIColor blackColor];
_titleLabel.highlightedTextColor = [UIColor whiteColor];
[self.contentView addSubview:_titleLabel];
// feed ラベルの作成
_feedLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_feedLabel.font = [UIFont systemFontOfSize:12.0f];
_feedLabel.textColor = [UIColor grayColor];
_feedLabel.highlightedTextColor = [UIColor whiteColor];
[self.contentView addSubview:_feedLabel];
// UIImageView の作成
UIImage* image;
image = [UIImage imageNamed:@"numberBackground.png"];
_numberBackgroundImageView = [[UIImageView alloc] initWithImage:image];
[self.contentView addSubView:_numberBackgroundImageView];
// 数字ラベル作成
_numberLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_numberLabel.font = [UIFont systemFontOfSize:17.0f];
_umberLabel.textColor = [UIColor whiteColor];
_numberLabel.backgroundColor = [UIColor clearColor];
_numberLabel.textAlignment = UITextAlignmentCenter;
[self.contentView addSubview:_numberLabel];
return self;
サブビューのインスタンス化にはinitWithFrame:を使用。
この段階ではインスタンス化を行うのみで、領域サイズも0で構わない。
また、作成したインスタンスに対してautoreleaseを呼んでいない点にも注意。
これはdeallocで解放を行う。
6.2.4. コンテンツのためのアクセッサメソッド
作成したサブビューに値を設定するための、アクセッサメソッドを用意する。
方法は2つ。
1)追加したサブビューを、そのままプロパティとして提供する。
// サブビューのためのアクセッサ
@property (nonatomic, readonly) UILabel* _titleLabel;
@property (nonatomic, readonly) UILabel* _feedLabel;
実装は @synthesize を使ってプロパティメソッドを作成する。
// プロパティの実装
@synthesize titleLabel = _titleLabel;
@synthesize feedLabel = _feedLabel;
利点は、コントローラ側で細かくサブビューの状態を制御できること。
欠点は、値を設定した際の再レイアウトを自前で行う必要があること。
2)コンテンツ自体を表すオブジェクトへのアクセッサを提供する。
// コンテンツのためのアクセッサ
@property (nonatomic) int itemNumber;
実装はアクセッサメソッドを上書きして行う。
- (int)itemNumber {
// ラベルから数値を取得
return [_numberLabel.text intValue];
}
- (void)setItemNumber:(int)itemNumber {
// ラベルにテキストを設定
_numberLabel.text = [NSString stringWithFormat:@"%d", itemNumber];
// セルの再レイアウト
[self setNeedsLayout];
}
利点は、値を設定すると同時に再レイアウトを行えること。
欠点は、アクセッサメソッドの上書きをしてやる必要があること。
6.2.5. サブビューのレイアウト
作成したサブビューのレイアウトについて。
レイアウトはlayoutSubviewsメソッド内で行う。
初期化やアクセッサの中では行わない。
- (void)layoutSubviews {
// 親クラスのlayoutSubviewsを呼び出す
[super layoutSubviews];
// contentViewのサイズを取得
CGRect bounds;
bounds = self.contentView.bounds;
// titleLabelのレイアウト実行
...
// feedLabelのレイアウト実行
...
6.2.6. セルのハイライト⁄選択
カスタマイズしたサブビューでの、ハイライトや選択状態表示について。
標準のセルは、既にこの機能を持っているので、
カスタマイズしたサブビューでも、これを上書きして使用する。
- (void)setHighlighted:(BOOL)highlighted animated:animated {
// 親クラスのsetHighlighted:animatedを呼び出し
[super setHighlighted:selected animated:animated];
// ラベルのハイライトを設定
_titleLabel.highlighted = highlighted;
_feedLabel.highlighted = highlighted;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
// 親クラスのsetSelected:animatedを呼び出す
[super setSelected:selected animated:animated];
// ラベルのハイライトを設定
_titleLabel.highlighted = selected;
_feedLabel.highlighted = selected;
}
UILabelにはhighlightedプロパティがある。
これがYESになると、テキスト色にhighlightedTextColorが使用される。
【おまけ】GUI関係が出てくると気がはやる
テーブルとテーブルセル、このビューレイアウトは、
iPhoneアプリの大半で使われているものです。
このあたりの内容が出てくると、さすがに気がはやります。
現在、「読書と実践」の内で「読書」の部分しか、こなせていません。
「実践」が出来ていないのです。
本の内容に従って実際にRSSReaderを作成しつつ、
記事を書き進めるのがベストなのですが、
Xcode4へのバージョンアップなどもあり、
「実践」が追いついていません。
今は、「早く実際にコーディングしたい」という気持ちと、
「とにかく、ひと通り終わらせてしまいたい」と言う気持ちがせめぎ合い中。 *02あれ?昨日も同じ様なことを言っていた気が…
まあ、あと3章と少し。
何とか、行けるところまで頑張ってみましょうか。

