webentwicklung-frage-antwort-db.com.de

Laden einer wiederverwendbaren UITableViewCell von einer Nib

Ich bin in der Lage, benutzerdefinierte UITableViewCells zu entwerfen und sie mit der im Thread unter http://forums.macrumors.com/showthread.php?t=545061 beschriebenen Technik problemlos zu laden. Mit dieser Methode können Sie die Zelle jedoch nicht mehr mit einem reuseIdentifier initialisieren, was bedeutet, dass Sie bei jedem Aufruf ganz neue Instanzen jeder Zelle erstellen müssen. Hat jemand eine gute Möglichkeit gefunden, bestimmte Zelltypen für die Wiederverwendung zwischenzuspeichern, sie aber dennoch in Interface Builder entwerfen zu können?

89
Greg Martin

Implementieren Sie einfach eine Methode mit der entsprechenden Methodensignatur:

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

Da Sie die Zelle in Interface Builder erstellen, müssen Sie dort lediglich die Wiederverwendungs-ID festlegen:

IB_reuse_identifier

Wenn Sie Xcode 4 ausführen, überprüfen Sie die Registerkarte "Attribute":

enter image description here

(Bearbeiten: Nachdem Ihre XIB von XCode generiert wurde, enthält sie eine leere UIView, wir benötigen jedoch eine UITableViewCell. Sie müssen daher die UIView manuell entfernen und eine Tabellensichtzelle einfügen. Natürlich zeigt IB keine UITableViewCell-Parameter für a an UIView.)

119
Tim Keating

Jetzt gibt es in iOS 5 eine geeignete UITableView-Methode dafür:

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

Ich kann mich nicht erinnern, wo ich diesen Code ursprünglich gefunden habe, aber es hat bisher großartig für mich funktioniert.

- (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;
}

Beispiel für ein Interface Builder-Setup ...

alt text

47
jrainbow

Schauen Sie sich die Antwort an, die ich auf diese Frage gegeben habe:

Ist es möglich, NSCell-Unterklassen im Interface Builder zu entwerfen?

Es ist nicht nur möglich, eine UITableViewCell in IB zu entwerfen, es ist auch wünschenswert, da sonst die gesamte manuelle Verdrahtung und Platzierung mehrerer Elemente sehr mühsam ist. Die Leistung ist in Ordnung, solange Sie darauf achten, dass alle Elemente, wenn möglich, undurchsichtig sind. Die Wiederverwendungs-ID wird in IB für die Eigenschaften von UITableViewCell festgelegt. Anschließend verwenden Sie die entsprechende Wiederverwendungs-ID im Code, wenn Sie versuchen, die Warteschlange zu entfernen.

Ich habe auch von einigen Vortragenden auf der WWDC im letzten Jahr gehört, dass Sie in IB keine Tabellenzellen erstellen sollten, aber es ist eine Ladung Koje.

Ab iOS 4.0 gibt es in den iOS-Dokumenten spezielle Anweisungen, mit denen diese Funktion superschnell ausgeführt werden kann:

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

Scrollen Sie nach unten, wo es um die Unterklasse von UITableViewCell geht.

7
Ben Mosher

Hier ist eine andere Option:

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

Diese Technik funktioniert auch und erfordert kein funky ivar in Ihrem View-Controller für die Speicherverwaltung. Hier befindet sich die benutzerdefinierte Tabellenzelle in einer xib mit dem Namen "CustomCell.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

Ich erstelle meine benutzerdefinierten Ansichtszellen auf ähnliche Weise - mit der Ausnahme, dass ich die Zelle über ein IBOutlet verbinde.

Das [nib objectAt...] Ansatz ist anfällig für Änderungen an Positionen von Elementen im Array.

Der UIViewController Ansatz ist gut - habe es gerade ausprobiert und es funktioniert gut genug.

ABER...

In allen Fällen wird der Konstruktor initWithStyle NICHT aufgerufen, sodass keine Standardinitialisierung durchgeführt wird.

Ich habe verschiedene Stellen über die Verwendung von initWithCoder oder awakeFromNib gelesen, aber keine schlüssigen Beweise dafür, dass beides der richtige Weg ist.

Abgesehen vom expliziten Aufruf einer Initialisierungsmethode in der cellForRowAtIndexPath -Methode habe ich noch keine Antwort darauf gefunden.

2
sww

Vor einiger Zeit habe ich unter blog.atebits.com einen großartigen Blogeintrag zu diesem Thema gefunden und seitdem angefangen, die ABTableViewCell-Klasse von Loren Brichter für alle meine UITableViewCells zu verwenden.

Am Ende haben Sie einen einfachen Container UIView, um alle Ihre Widgets zu platzieren, und das Scrollen ist blitzschnell.

Hoffe das ist nützlich.

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

Die Louis-Methode hat bei mir funktioniert. Dies ist der Code, den ich verwende, um die UITableViewCell aus der Schreibfeder zu erstellen:

- (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

Die Gustavogb-Lösung funktioniert bei mir nicht. Ich habe Folgendes versucht:

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

Es scheint zu funktionieren. Die blogTableViewCell ist das IBOutlet für die Zelle und ChainesController ist der Eigentümer der Datei.

1
groumpf

In den UITableView-Dokumenten zu dequeueWithReuseIdentifier: "Eine Zeichenfolge, die das Zellobjekt angibt, das wiederverwendet werden soll. Standardmäßig ist die Kennung einer wiederverwendbaren Zelle der Klassenname. Sie können sie jedoch in einen beliebigen Wert ändern."

Das Überschreiben von -reuseIdentifer selbst ist riskant. Was passiert, wenn Sie zwei Unterklassen Ihrer Zell-Unterklasse haben und beide in einer einzigen Tabellenansicht verwenden? Wenn sie den Aufruf zur erneuten Verwendung des Bezeichners an super senden, wird eine Zelle des falschen Typs aus der Warteschlange entfernt. Ich denke, Sie müssen die reuseIdentifier-Methode überschreiben, aber sie muss einen ersetzten Bezeichner zurückgeben Zeichenfolge. Wenn keine angegeben wurde, kann die Klasse auch als Zeichenfolge zurückgegeben werden.

1
SK9

Ich habe die Anweisungen von Apple befolgt, die von Ben Mosher verlinkt wurden (danke!), Aber festgestellt, dass Apple ein wichtiger Punkt ausgelassen hat. Das Objekt, das sie in IB entwerfen, ist nur eine UITableViewCell, ebenso wie die Variable, die sie daraus laden Wenn Sie es jedoch tatsächlich als benutzerdefinierte Unterklasse von UITableViewCell einrichten und die Codedateien für die Unterklasse schreiben, können Sie IBOutlet-Deklarationen und IBAction-Methoden in den Code schreiben und sie mit Ihren benutzerdefinierten Elementen in IB verbinden Sie müssen View-Tags verwenden, um auf diese Elemente zuzugreifen, und Sie können jede Art von verrückter Zelle erstellen, die Sie möchten.

0
David Casseres

Bei einem der iPhone Tech Talks habe ich einen iPhone-Techniker danach gefragt. Seine Antwort war: "Ja, es ist möglich, IB zum Erstellen von Zellen zu verwenden. Aber nicht. Bitte, nicht."

0
August