iOS6を使用する場合のUITableViewCellのスタイルの設定UITableViewdequeueReusableCellWithIdentifier:forIndexPath:


82

UITableViewCellStyleiOS 6forで新しいメソッドを使用するときにを設定する方法を見つけようとしていますUITableView

以前は、UITableViewCellIUITableViewCellStyleを作成するときに、呼び出し時にさまざまなタイプのデフォルトセルを作成するように列挙型を変更していましたinitWithStyle:が、収集できるものから、これは当てはまりません。

UITableView州のAppleドキュメント:

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

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

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

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

サブクラス化したくありません。iOS6より前のバージョンUITableViewCellと同じようにデフォルトのタイプを変更したいだけです。Appleが拡張メソッドを提供するのは奇妙に思えますが、その実装をサポートするための最小限のドキュメントしかありません。

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

回答:


106

サブクラスを作成したくないとおっしゃっていたのは知っていますが、それは避けられないようです。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;
}

また、セルが要求されるたびに送信するのregisterClass:forCellReuseIdentifier:viewDidLoadはなく、送信する方がよい場合があります。

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

4
私はこれが確かに事実であると思い始めていました。これは大きな問題ではありませんUITableViewCellが、他のデフォルトのスタイルを取得するためにサブクラス化する必要があるのは、不要なファイルを作成するだけなので面倒です。あなたのコメントと私の疑いを確認してくれてありがとう。
CaptainRedmuff 2012年

11
サブクラス化する代わりに、まだ有効な古いiOS5メソッドを使用できることを忘れないでください。そうすれば、自分で好きなタイプのセルスタイルを初期化できます。他の答えを参照してください。
SpacyRicochet 2013年

60

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

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


1
派手な新しい方法使用する必要がないことを指摘することに賛成。それらがあなたの目的に合っている場合、または代替案が非推奨である場合のみ。
SpacyRicochet 2013年

特に熱心な場合はdequeueReusableCellWithIdentifier:forIndexPath:、古い方法でセルを構築する(そしてそれらを返す)いくつかの識別子を提供するためにオーバーライドするのは問題ありません。他の識別子はsuperを呼び出し、それを返します。NSDictionaryその種類の識別子のコンストラクタブロックに識別子を1つ持つことは理にかなっているかもしれません。
ベンジョン2015年

11

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

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

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


7

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

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

次に、テーブルビューコントローラのviewDidLoadメソッドで次のようなものを呼び出します。

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

initWithStyle:reuseIdentifierは呼び出されません。
thierryb 2014年

0

ボロットの答えは正しいです。シンプルで、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")
}

-5

これに対する私の解決策は、initWithStyle: reuseIdentifier:を使用して取得した後に呼び出すこと[self.tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath]です。結局のところ、initは単なる別のセレクターであり、コンパイラーは、すでに初期化されたオブジェクトでそれを呼び出すことに制限を設けていません。ただし、initを呼び出した結果を使用しないと文句を言うので、次のようにします。

UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath];
cell = [cell initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cellId"];

これはSwiftでは機能しないと思います...


最もエレガントなソリューションimo。うまくいけば、initWithStyleの根性がすべてを再作成することはありません。
Scott Birksted 2015

2
ええと、あなたがこのようにそれをしているなら、あなたはデキューするものを完全に落とすことができると思います...
stk 2016年

1
セルの再利用は、パフォーマンスの高いUITableViewの鍵です。あなたの解決策は、セルを再利用しないことを提案しています。
Berik 2016

2
initWithStyle: reuseIdentifier2回目に呼び出すと、実際には新しく作成されたオブジェクトでセルが上書きされます。はい、メモリの割り当てはすでに行われており、新しいセルは同じメモリ位置を上書きしますが、実際には、再度初期化するとまったく新しいオブジェクトが作成されます。これは、そもそもセルを再利用することの要点であるすべての最適化を無効にします。
AnthonyMDev 2016年

1
従うのは良い解決策ではありません-この解決策を使用している場合は、少なくともセルのデキューを完全に削除する方が良いと思います
Sudara 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.