結局、本の内容をなぞるだけの状態になっていて、
こんなの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章と少し。
何とか、行けるところまで頑張ってみましょうか。



