2012-11-01 1 views
81

Ich versuche herauszufinden, wie UITableViewCellStyle bei Verwendung der neuen Methoden in iOS 6 für UITableView festgelegt wird.Festlegen des Stils von UITableViewCell bei Verwendung von iOS 6 UITableView dequeueReusableCellWithIdentifier: forIndexPath:

Früher, als ein UITableViewCell Schaffung würde ich die UITableViewCellStyle Enum ändern, um verschiedene Arten von Standard-Zellen zu erzeugen, wenn initWithStyle: Aufruf aber von dem, was ich sammeln kann, ist dies nicht mehr der Fall.

Die Apple-Dokumentation für UITableView heißt es:

Rückgabewert: Ein UITableViewCell Objekt mit der Wiederverwendung Kennung zugeordnet. Diese Methode gibt immer eine gültige Zelle zurück.

Diskussion: Aus Leistungsgründen eine Datenquelle der Tabelle Ansicht sollten generell UITableViewCell Objekte wiederverwenden, wenn es Zellen Zeilen in seiner Tableview zuordnet: cellForRowAtIndexPath: Methode. Eine Tabellensicht verwaltet eine Warteschlange oder Liste von UITableViewCell-Objekten, die die Datenquelle zur Wiederverwendung markiert hat. Rufen Sie diese Methode von Ihrem Datenquellenobjekt auf, wenn Sie aufgefordert werden, eine neue Zelle für die Tabellenansicht bereitzustellen. Mit dieser Methode wird eine vorhandene Zelle aus der Warteschlange entfernt, wenn eine vorhanden ist, oder eine neue Zelle basierend auf der zuvor registrierten Klassen- oder Nib-Datei erstellt.

Wichtige: Sie müssen eine Klasse oder nib Datei registrieren mit dem registerNib: forCellReuseIdentifier: oder register: forCellReuseIdentifier: Verfahren vor dem Aufruf dieser Methode.

Wenn Sie eine Klasse für den angegebenen Bezeichner registriert haben und eine neue Zelle erstellt werden muss, initialisiert diese Methode die Zelle durch Aufrufen der Methode initWithStyle: reuseIdentifier:. Bei Nib-basierten Zellen lädt diese Methode das Zellobjekt aus der bereitgestellten NIB-Datei. Wenn eine vorhandene Zelle für die Wiederverwendung verfügbar war, ruft diese Methode stattdessen die prepareForReuse-Methode der Zelle auf.

Dies ist, wie meine neue cellForRowAtIndexPath sieht nach den neuen Methoden der Umsetzung:

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

Der Code, den ich bisher habe funktioniert gut, aber immer den Standardstil. Wie kann ich das ändern, damit ich Zellen mit den anderen Stilen wie UITableViewCellStyleDefault, UITableViewCellStyleValue1, UITableViewCellStyleValue2 und UITableViewCellStyleSubtitle erstellen kann?

Ich möchte keine Unterklasse UITableViewCell, Ich möchte nur den Standardtyp ändern, wie ich vor iOS 6 tun konnte. Es scheint seltsam, dass Apple erweiterte Methoden, aber mit minimalen Dokumentation zur Unterstützung ihrer Implementierung bieten würde.

Hat jemand dies gemeistert, oder läuft auf ein ähnliches Problem? Ich habe Mühe, überhaupt vernünftige Informationen zu finden.

Antwort

103

Ich weiß, Sie sagten, Sie wollten keine Unterklasse erstellen, aber es sieht unvermeidlich aus. Basierend auf der Code-Anordnung, während im Simulator iOS 6.0 zu testen, UITableView neuen Instanzen von UITableViewCell (oder ihren Unterklassen) durch

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

Mit anderen Worten, der Stil (UITableViewCellStyleDefault) gesendet erzeugt Durchführung erscheint hartcodiert werden.Um dies zu umgehen, müssen Sie eine Unterklasse erstellen, die die Standard-Initialisierung überschreibt initWithStyle:reuseIdentifier: und übergibt den Stil, den Sie verwenden möchten:

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

Auch könnte es besser sein registerClass:forCellReuseIdentifier: in viewDidLoad zu schicken, statt es zu tun jedes Mal, wenn eine Zelle angefordert wird:

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

Ich begann in der Tat davon aus, dass dies der Fall sein würde. Es ist kein großes Problem, aber die 'UITableViewCell'-Unterklasse zu entfernen, um die anderen Standardstile zu erhalten, ist ein Problem, da es nur unnötige Dateien erzeugt. Danke für deinen Kommentar und bestätige meinen Verdacht. – CaptainRedmuff

+11

Vergessen Sie nicht, dass Sie anstelle der Unterklassen die alte iOS5-Methode verwenden können, die immer noch gültig ist.Auf diese Weise können Sie jeden gewünschten Zellstil initialisieren. Siehe die andere Antwort. – SpacyRicochet

60

dequeueReusableCellWithIdentifier ist nicht veraltet, so dass Sie nicht die neue dequeueReusableCellWithIdentifier:forIndexPath: verwenden müssen.

Verwenden Sie die neue Methode zusammen mit der entsprechenden register-Methode (in viewDidLoad), wenn Sie eine benutzerdefinierte Zellklasse verwenden, aber die alte Methode verwenden, wenn Sie eine der UITableViewCellStyle-Enums verwenden möchten.

+1

Upvoted, um darauf hinzuweisen, dass Sie * die neuen Methoden nicht verwenden müssen. Nur wenn sie Ihrem Zweck entsprechen oder wenn die Alternativen veraltet sind. – SpacyRicochet

+0

Wenn Sie besonders interessiert sind, ist es in Ordnung, 'dequeueReusableCellWithIdentifier: forIndexPath:' zu überschreiben, um einige Bezeichner bereitzustellen, die Zellen auf die alte Art aufbauen (und zurückgeben). Andere Bezeichner rufen super auf und geben das zurück. Es könnte sinnvoll sein, ein 'NSDictionary' von Bezeichnern zu Konstruktorblöcken für diese Art von Bezeichnern zu haben. – Benjohn

11

Sie können mithilfe des Storyboard Interface Builder eine Fremdunterklasse vermeiden:

  1. In der Storyboard-Ansicht wählen Sie die Tabelle Ansicht Zelle Prototyp Zelle (auf der Tabellenansicht)
  2. In den Utilities zu erfahren, in der Inspektor Attribute, ändern Sie den Stil-Wert
  3. (Optional) andere Werte ändern, wie Auswahl und Zubehör

die neuen iOS 6.0 dequeueReusableCellWithIdentifier:forIndexPath: verwendet diese Werte, wenn neue Zellen zugewiesen und zurückgegeben werden. (Getestet auf einer iOS 6.0-Kompilierung mit Xcode 4.5.2)

6

Eine weitere Alternative, die eine Datei speichert, besteht darin, eine Nib zu erstellen und stattdessen registerNib:forCellReuseIdentifier: zu verwenden.

Die Erstellung der Nib ist einfach: Erstellen Sie eine neue .xib-Datei in Interface Builder. Löschen Sie die Standardansicht. Fügen Sie ein Tabellenansichtszellenobjekt hinzu. Ändern Sie mithilfe des Informationsfensters "Attribute" den Stil für die Zelle. (Hier haben Sie auch die Möglichkeit, die Zelle weiter gestaltet andere Attribute anpassen.)

dann in der Tabelle viewDidLoad Methodenaufruf etwas Ansicht Controller wie:

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

initWithStyle: reuseIdentifier wird nicht aufgerufen. – thierryb

-5

zu Meiner Lösung ist initWithStyle: reuseIdentifier: rief nach Ich habe es mit [self.tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath] erhalten. Immerhin ist init nur ein anderer Selektor, und der Compiler macht keine Einschränkungen für den Aufruf eines bereits initialisierten Objekts. Es wird jedoch bemängeln nicht das Ergebnis des Aufrufs init verwenden, so dass ich tun:

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

Ich stelle mir das nicht in Swift funktioniert ...

+0

Dies funktioniert in Swift gut. – faraquet99

+0

Die eleganteste Lösung imo. Hoffentlich erstellt der Mut von initWithStyle nicht alles neu. –

+2

Nun, ich denke, wenn du es so machst, kannst du das aus der Warteschleife fallen lassen ... – stk

0

Bolot Antwort die richtige ist. Einfach und Sie müssen keine XIB-Datei erstellen.

Ich wollte nur für seine Antwort zu aktualisieren, wer auch immer es mit Swift statt Objective-C tut:

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

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