Impostazione dello stile di UITableViewCell quando si utilizza iOS 6 UITableView dequeueReusableCellWithIdentifier: forIndexPath:

Sto cercando di capire come impostare UITableViewCellStyle quando si utilizzano i nuovi metodi in iOS 6 per UITableView .

In precedenza, durante la creazione di UITableViewCell avrei modificato l’ UITableViewCellStyle per creare diversi tipi di celle predefinite quando si chiamava initWithStyle: ma da quello che posso raccogliere, non è più così.

La documentazione di Apple per gli stati di UITableView :

Valore restituito : un object UITableViewCell con l’identificatore di riutilizzo associato. Questo metodo restituisce sempre una cella valida.

Discussione : per motivi di prestazioni, l’origine dati di una vista tabella dovrebbe generalmente riutilizzare oggetti UITableViewCell quando assegna le celle alle righe nella sua tabellaView: cellForRowAtIndexPath: method. Una vista tabella mantiene una coda o un elenco di oggetti UITableViewCell che l’origine dati ha contrassegnato per il riutilizzo. Chiamare questo metodo dall’object di origine dati quando viene richiesto di fornire una nuova cella per la vista tabella. Questo metodo rimuove una cella esistente se ne è disponibile una o ne crea una nuova in base al file di class o pennino precedentemente registrato.

Importante : è necessario registrare un file di class o pennino utilizzando registerNib: forCellReuseIdentifier: o registerClass: forCellReuseIdentifier: metodo prima di chiamare questo metodo.

Se hai registrato una class per l’identificatore specificato e una nuova cella deve essere creata, questo metodo inizializza la cella chiamando initWithStyle: reuseIdentifier: method. Per le celle basate su pennino, questo metodo carica l’object cella dal file di pennino fornito. Se una cella esistente era disponibile per il riutilizzo, questo metodo chiama invece il metodo prepareForReuse della cella.

Ecco come appare il mio nuovo cellForRowAtIndexPath dopo aver implementato i nuovi metodi:

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

Il codice che ho finora funziona bene, ma restituisce sempre lo stile predefinito. Come posso cambiarlo così posso creare celle con altri stili come UITableViewCellStyleDefault , UITableViewCellStyleValue1 , UITableViewCellStyleValue2 e UITableViewCellStyleSubtitle ?

Non voglio sottoclass UITableViewCell , voglio solo cambiare il tipo predefinito che potrei fare prima di iOS 6. Appare strano che Apple fornisca metodi avanzati ma con una documentazione minima a supporto della loro implementazione.

Qualcuno ha imparato questo o si è imbattuto in un problema simile? Sto faticando a trovare qualsiasi informazione ragionevole.

So che hai detto che non volevi creare una sottoclass, ma sembra inevitabile. Basato sul codice assembly durante il test nel simulatore iOS 6.0, UITableView crea nuove istanze di UITableViewCell (o delle sue sottoclassi) eseguendo

 [[ alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:] 

In altre parole, lo stile inviato ( UITableViewCellStyleDefault ) sembra essere hardcoded. Per initWithStyle:reuseIdentifier: questo, è necessario creare una sottoclass che sostituisca l’inizializzatore predefinito initWithStyle:reuseIdentifier: e passa lo stile che si desidera utilizzare:

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

Inoltre, potrebbe essere meglio inviare registerClass:forCellReuseIdentifier: in viewDidLoad , invece di farlo ogni volta che viene richiesta una cella:

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

dequeueReusableCellWithIdentifier non è deprecato quindi non è necessario utilizzare il nuovo dequeueReusableCellWithIdentifier:forIndexPath:

Utilizzare la nuova modalità insieme al metodo di registrazione appropriato (in viewDidLoad) se si utilizza una class di celle personalizzata ma si utilizza la vecchia modalità se si desidera utilizzare una delle enumerazioni di UITableViewCellStyle.

Puoi evitare una sottoclass estranea usando il builder dell’interfaccia storyboard:

  1. Nella visualizzazione Storyboard, seleziona la cella prototype cella della vista tabella (nella vista tabella)
  2. Nella vista Utilità, nella finestra di ispezione Attributi, modifica il valore dello stile
  3. (Facoltativamente) Modificare altri valori come Selezione e Accessori

Il nuovo iOS 6.0 dequeueReusableCellWithIdentifier:forIndexPath: usa quei valori quando si assegnano nuove celle e le si restituiscono. (Testato su una compilation iOS 6.0 usando Xcode 4.5.2)

Un’altra alternativa che salva un file consiste nel creare un pennino e utilizzare registerNib:forCellReuseIdentifier: invece.

Creare il pennino è semplice: crea un nuovo file .xib in Interface Builder. Elimina la vista predefinita. Aggiungi un object cella Visualizza tabella. Utilizzando la finestra di ispezione Attributi, modifica lo stile della cella. (Qui hai anche la possibilità di personalizzare ulteriormente la cella regolando altri attributi.)

Quindi nella tua vista tabella il metodo viewDidLoad del controller chiama qualcosa come:

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

La risposta di Bolot è corretta. Semplice e non è necessario creare alcun file XIB.

Volevo solo aggiornare la sua risposta per chiunque lo stia usando Swift invece di Objective-C:

 override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: .value1, reuseIdentifier: reuseIdentifier) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } 

La mia soluzione è chiamare initWithStyle: reuseIdentifier: dopo averlo ottenuto usando [self.tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath] . Dopotutto, init è solo un altro selettore e il compilatore non impone restrizioni sul chiamarlo su un object già inizializzato. Tuttavia si lamenterà di non utilizzare il risultato di chiamare init, quindi faccio:

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

Immagino che questo non funzionerà in Swift …