web-dev-qa-db-ja.com

iOS 6 UITableView dequeueReusableCellWithIdentifier:forIndexPathを使用する場合のUITableViewCellのスタイルの設定:

IOS 6でUITableViewCellStyleの新しいメソッドを使用するときに、UITableViewを設定する方法を考えています。

以前は、UITableViewCellを作成するときに、initWithStyle:を呼び出すときにUITableViewCellStyle列挙型を変更してさまざまな種類のデフォルトセルを作成していましたが、収集できるものではありません。

Apple UITableViewのドキュメント:

戻り値:関連する再利用識別子を持つUITableViewCellオブジェクト。このメソッドは常に有効なセルを返します。

Discussion:パフォーマンス上の理由から、Table Viewのデータソースは通常、tableView:cellForRowAtIndexPath:メソッドの行にセルを割り当てるときにUITableViewCellオブジェクトを再利用する必要があります。テーブルビューは、データソースが再利用のためにマークしたUITableViewCellオブジェクトのキューまたはリストを保持します。テーブルビューに新しいセルを提供するように求められたら、データソースオブジェクトからこのメソッドを呼び出します。このメソッドは、既存のセルが使用可能な場合、既存のセルをデキューするか、以前に登録したクラスまたはnibファイルに基づいて新しいセルを作成します。

重要:このメソッドを呼び出す前に、registerNib:forCellReuseIdentifier:またはregisterClass:forCellReuseIdentifier:メソッドを使用してクラスまたはnibファイルを登録する必要があります。

指定した識別子のクラスを登録し、新しいセルを作成する必要がある場合、このメソッドはinitWithStyle:reuseIdentifier:メソッドを呼び出してセルを初期化します。 nibベースのセルの場合、このメソッドは提供されたnibファイルからセルオブジェクトをロードします。既存のセルを再利用できる場合、このメソッドは代わりにセルのprepareForReuseメソッドを呼び出します。

これは、新しいメソッドを実装した後の新しいcellForRowAtIndexPathの外観です。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"cell_identifier";

    [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellIdentifier];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    return cell;
}

これまでのコードは正常に機能しますが、常にデフォルトのスタイルを返します。これを変更して、UITableViewCellStyleDefaultUITableViewCellStyleValue1UITableViewCellStyleValue2UITableViewCellStyleSubtitleなどの他のスタイルのセルを作成するにはどうすればよいですか?

UITableViewCellをサブクラス化したくありません。iOS6より前にできるようにデフォルトの型を変更したいだけです。Appleは拡張メソッドを提供するが、実装をサポートするための最小限のドキュメント。

誰もがこれをマスターしたか、同様の問題に遭遇しましたか?合理的な情報を見つけるのに苦労しています。

81
CaptainRedmuff

サブクラスを作成したくないと言っていましたが、避けられないように見えます。 iOS 6.0シミュレーターでのテスト中のアセンブリコードに基づいて、UITableViewは以下を実行してUITableViewCell(またはそのサブクラス)の新しいインスタンスを作成します

[[<RegisteredClass> alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:<ReuseIdentifier>]

つまり、送信されたスタイル(UITableViewCellStyleDefault)はハードコードされているようです。これを回避するには、デフォルトの初期化子initWithStyle:reuseIdentifier:をオーバーライドし、使用するスタイルを渡すサブクラスを作成する必要があります。

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    // ignore the style argument, use our own to override
    self = [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier];
    if (self) {
        // If you need any further customization
    }
    return self;
}

また、セルがリクエストされるたびに送信するのではなく、viewDidLoadregisterClass:forCellReuseIdentifier:を送信する方がよい場合があります。

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerClass:<RegisteredClass> forCellReuseIdentifier:<ReuseIdentifier>];
}
104
bolot

dequeueReusableCellWithIdentifierは非推奨ではないため、新しいdequeueReusableCellWithIdentifier:forIndexPath:を使用する必要はありません。

カスタムセルクラスを使用している場合は適切なregisterメソッド(viewDidLoad内)とともに新しい方法を使用しますが、UITableViewCellStyle列挙型のいずれかを使用する場合は古い方法を使用します。

60
Murray Sagal

ストーリーボードインターフェイスビルダーを使用すると、無関係なサブクラスを回避できます。

  1. ストーリーボードビューで、テーブルビューのセルプロトタイプセル(テーブルビュー上)を選択します。
  2. [ユーティリティ]ビューの[属性]インスペクターで、スタイルの値を変更します
  3. (オプション)選択やアクセサリなどの他の値を変更します

新しいiOS 6.0 dequeueReusableCellWithIdentifier:forIndexPath:は、新しいセルを割り当ててそれらを返すときにこれらの値を使用します。 (Xcode 4.5.2を使用したiOS 6.0コンパイルでテスト済み)

11
Jeff Collier

1つのファイルを保存する別の方法は、ペン先を作成し、代わりにregisterNib:forCellReuseIdentifier:を使用することです。

ペン先の作成は簡単です:Interface Builderで新しい.xibファイルを作成します。デフォルトビューを削除します。テーブルビューセルオブジェクトを追加します。属性インスペクターを使用して、セルのスタイルを変更します。 (ここでは、他の属性を調整してセルをさらにカスタマイズする機会もあります。)

次に、Table View ControllerのviewDidLoadメソッドで次のように呼び出します:

[self.tableView registerNib:[UINib nibWithNibName:@"StyleSubtitleTableCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"Cell"];
7
Mr. Berna

ボロットの答えは正しいです。シンプルで、XIBファイルを作成する必要はありません。

私はObjective-Cの代わりにSwiftを使用してそれをしている人のために彼の答えを更新したかった:

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: .value1, reuseIdentifier: reuseIdentifier)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
0
Gabriel Oliva