web-dev-qa-db-ja.com

再利用可能なUITableViewCellをペン先からロードする

http://forums.macrumors.com/showthread.php?t=545061 にあるスレッドで説明されている手法を使用して、カスタムUITableViewCellsを設計し、それらを正常にロードできます。ただし、そのメソッドを使用すると、reuseIdentifierを使用してセルを初期化できなくなります。つまり、呼び出しごとに各セルのまったく新しいインスタンスを作成する必要があります。特定のセルタイプを再利用のためにキャッシュするのに、Interface Builderでそれらを設計することができる優れた方法を誰かが見つけましたか?

89
Greg Martin

適切なメソッドシグネチャでメソッドを実装するだけです。

- (NSString *) reuseIdentifier {
  return @"myIdentifier";
}
74
Louis Gerbarg

実際、Interface Builderでセルを構築しているので、再利用識別子をそこに設定するだけです:

IB_reuse_identifier

または、Xcode 4を実行している場合、[属性インスペクター]タブを確認します。

enter image description here

(編集:XCodeによってXIBが生成された後、空のUIViewが含まれますが、UITableViewCellが必要です。そのため、UIViewを手動で削除し、Table View Cellを挿入する必要があります。もちろん、IBはUIView。)

119
Tim Keating

さて、iOS 5にはそのための適切なUITableViewメソッドがあります:

- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
66
wzs

元々このコードを見つけた場所を思い出すことはできませんが、これまでのところうまく機能しています。

- (UITableViewCell *)tableView:(UITableView *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"CustomTableCell";
    static NSString *CellNib = @"CustomTableCellView";

    UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
        cell = (UITableViewCell *)[nib objectAtIndex:0];
    }

    // perform additional custom work...

    return cell;
}

Interface Builderセットアップの例...

alt text

47
jrainbow

この質問に私が与えた答えを見てください:

Interface BuilderでNSCellサブクラスを設計することは可能ですか?

IBでUITableViewCellを設計するだけでなく、それが望ましいのは、そうしないと、複数の要素の手動による配線と配置がすべて非常に面倒なためです。すべての要素を可能な限り不透明にするように注意している限り、パフォーマンスは良好です。 UITableViewCellのプロパティに対して、reuseIDがIBに設定されている場合、デキューするときにコード内で一致する再利用IDを使用します。

また、昨年WWDCのプレゼンターの何人かから、IBでテーブルビューセルを作成するべきではないと聞いたが、それはたくさんの寝台だ。

IOS 4.0頃の時点で、この機能を超高速にするiOSドキュメントに特定の指示があります。

http://developer.Apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//Apple_ref/doc/uid/TP40007451-CH7

UITableViewCellのサブクラス化について説明する場所までスクロールします。

7
Ben Mosher

別のオプションを次に示します。

NSString * cellId = @"reuseCell";  
//...
NSArray * nibObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomTableCell" owner:nil options:nil];

for (id obj in nibObjects)
{
    if ([obj isKindOfClass:[CustomTableCell class]])
    {
        cell = obj;
        [cell setValue:cellId forKey:@"reuseIdentifier"];
        break;
    }
}
6
JDL

この手法も機能し、メモリ管理のためにView Controllerにファンキーなivarを必要としません。ここでは、カスタムテーブルビューセルは「CustomCell.xib」という名前のxibにあります。

 static NSData *sLoadedCustomCell = nil;

 cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell"];
 if (cell == nil) 
 {
   if (sLoadedCustomCell == nil) 
   {        
      // Load the custom table cell xib
      // and extract a reference to the cell object returned
      // and cache it in a static to avoid reloading the nib again.

      for (id loadedObject in [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:nil options:nil]) 
      {
        if ([loadedObject isKindOfClass:[UITableViewCell class]]) 
        {
          sLoadedCustomCell = [[NSKeyedArchiver archivedDataWithRootObject: loadedObject] retain];
          break;
        }
    }
    cell = (UITableViewCell *)[NSKeyedUnarchiver unarchiveObjectWithData: sLoadedCustomCell];
  }
2
Bill Garrison

同様の方法でカスタムビューセルを作成します。ただし、IBOutletを介してセルを接続します。

[nib objectAt...]アプローチは、配列内のアイテムの位置を変更する可能性があります。

UIViewControllerアプローチは優れています-試しただけで、十分に機能します。

しかし...

すべての場合において、initWithStyleコンストラクターは呼び出されないため、デフォルトの初期化は行われません。

initWithCoderまたはawakeFromNibの使用に関するさまざまな箇所を読みましたが、これらのいずれかが正しい方法であるという決定的な証拠はありません。

cellForRowAtIndexPathメソッドで初期化メソッドを明示的に呼び出すことを除けば、これに対する答えはまだ見つかりません。

2
sww

しばらく前に、このトピックに関する素晴らしいブログ記事を blog.atebits.com で見つけ、それ以来、Loren Brichter ABTableViewCellクラスを使用してすべてのUITableViewCellを実行し始めました。

すべてのウィジェットを配置するためのシンプルなコンテナーUIViewが作成され、スクロールは非常に高速です。

これが役立つことを願っています。

2
eric
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *simpleTableIdentifier = @"CustomCell";

CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
    cell = [nib objectAtIndex:0];

    [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}         

return cell;
}
2
Mohit

ルイメソッドは私のために働いた。これは、nibからUITableViewCellを作成するために使用するコードです。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{   
    UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"CustomCellId"];

    if (cell == nil) 
    {
        UIViewController *c = [[UIViewController alloc] initWithNibName:@"CustomCell" bundle:nil];
        cell = (PostCell *)c.view;
        [c release];
    }

    return cell;
}
2
ggarber

Gustavogbソリューションは私には機能しません、私が試したのは:

ChainesController *c = [[ChainesController alloc] initWithNibName:@"ChainesController" bundle:nil];
[[NSBundle mainBundle] loadNibNamed:@"ChaineArticleCell" owner:c options:nil];
cell = [c.blogTableViewCell retain];
[c release];

うまくいくようです。 blogTableViewCellはセルのIBOutletであり、ChainesControllerはファイルの所有者です。

1
groumpf

dequeueWithReuseIdentifierに関するUITableViewドキュメントから:「再利用されるセルオブジェクトを識別する文字列。デフォルトでは、再利用可能なセルの識別子はクラス名ですが、任意の値に変更できます。」

-reuseIdentiferをオーバーライドするのは危険です。セルサブクラスの2つのサブクラスがあり、これらの両方を単一のテーブルビューで使用するとどうなりますか?再利用識別子の呼び出しをスーパーに送信すると、間違ったタイプのセルをデキューします。文字列。または、指定されていない場合は、クラスを文字列として返します。

1
SK9

私はBen MosherにリンクされたAppleの指示に従いました(ありがとう!)Appleは重要なポイントを省略しました。IBで設計するオブジェクトは、UITableViewCellです。しかし、実際にUITableViewCellのカスタムサブクラスとして設定し、サブクラスのコードファイルを記述する場合、コードにIBOutlet宣言とIBActionメソッドを記述し、IBのカスタム要素にそれらを関連付けることができます。ビュータグを使用してこれらの要素にアクセスする必要があり、任意の種類のクレイジーなセルを作成できます。これはCocoa Touchの天国です。

0
David Casseres

その価値については、iPhone Tech TalksでiPhoneのエンジニアに尋ねました。彼の答えは、「はい、IBを使用してセルを作成することは可能です。しかし、しないでください。しないでください。」

0
August