Domanda

Sono in grado di progettare UITableViewCells personalizzati e caricarli bene usando la tecnica descritta nel thread trovato in http://forums.macrumors.com/showthread.php?t=545061 . Tuttavia, l'utilizzo di questo metodo non consente più di avviare la cella con un reuseIdentifier, il che significa che è necessario creare istanze completamente nuove di ogni cella ad ogni chiamata. Qualcuno ha trovato un buon modo per memorizzare ancora nella cache determinati tipi di celle per i riutilizzi, ma è ancora in grado di progettarli in Interface Builder?

È stato utile?

Soluzione

Basta implementare un metodo con la firma del metodo appropriata:

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

Altri suggerimenti

In realtà, poiché stai costruendo la cella in Interface Builder, imposta qui l'identificatore di riutilizzo:

 IB_reuse_identifier

O se stai eseguendo Xcode 4, controlla la scheda della finestra di ispezione Attributi:

inserisci qui la descrizione dell'immagine

(Modifica: dopo che XIB è stato generato da XCode, contiene un UIView vuoto, ma abbiamo bisogno di UITableViewCell; quindi è necessario rimuovere l'UIView manualmente e inserire una cella di visualizzazione tabella. Naturalmente, IB non mostrerà alcun UITableViewCell parametri per una vista UIV.)

Ora, in iOS 5 esiste un metodo UITableView appropriato per questo:

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

Non ricordo dove ho trovato questo codice in origine, ma finora ha funzionato benissimo per me.

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

Esempio di configurazione di Interface Builder ...

 alt text

Guarda la risposta che ho dato a questa domanda:

È possibile progettare sottoclassi NSCell in Interface Builder?

Non è solo possibile progettare un UITableViewCell in IB, è desiderabile perché altrimenti tutto il cablaggio manuale e il posizionamento di più elementi è molto noioso. Le prestazioni vanno bene fintanto che stai attento a rendere opachi tutti gli elementi quando possibile. ReuseID è impostato in IB per le proprietà di UITableViewCell, quindi si utilizza l'ID di riutilizzo corrispondente nel codice quando si tenta di dequeue.

Ho anche sentito da alcuni dei presentatori del WWDC l'anno scorso che non dovresti creare celle con vista tabella in IB, ma è un sacco di cuccette.

A partire da iOS 4.0, ci sono istruzioni specifiche nei documenti iOS che rendono questo lavoro superveloce:

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

Scorri verso il basso fino a dove parla della sottoclasse di UITableViewCell.

Ecco un'altra opzione:

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

Creo le celle di visualizzazione personalizzate in modo simile, tranne per il collegamento della cella tramite un IBOutlet.

L'approccio [nib objectAt ...] è suscettibile alle modifiche alle posizioni degli elementi nell'array.

L'approccio UIViewController è buono: l'ho appena provato e funziona abbastanza bene.

MA ...

In tutti i casi il costruttore initWithStyle NON viene chiamato, quindi non viene eseguita l'inizializzazione predefinita.

Ho letto vari luoghi sull'uso di initWithCoder o awakeFromNib , ma nessuna prova conclusiva che uno di questi sia il modo giusto.

Oltre a chiamare esplicitamente un metodo di inizializzazione nel metodo cellForRowAtIndexPath non ho ancora trovato una risposta a questo.

Qualche tempo fa ho trovato un ottimo post sul blog su questo argomento in blog.atebits.com e da allora hanno iniziato a utilizzare la classe ABTableViewCell di Loren Brichter per eseguire tutte le mie UITableViewCells.

Finisci con un semplice UIView contenitore per mettere tutti i tuoi widget e lo scorrimento è velocissimo.

Spero che sia utile.

Questa tecnica funziona anche e non richiede un ivar funky nel controller della vista per la gestione della memoria. Qui, la cella della vista tabella personalizzata vive in un xib chiamato " 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];
  }

Il metodo Louis ha funzionato per me. Questo è il codice che uso per creare UITableViewCell dal pennino:

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

La soluzione gustavogb non funziona per me, quello che ho provato è:

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

Sembra funzionare. Il blogTableViewCell è l'IBOutlet per la cella e ChainesController è il proprietario del file.

Dai documenti di UITableView relativi a dequeueWithReuseIdentifier : " Una stringa che identifica l'oggetto cella da riutilizzare. Per impostazione predefinita, l'identificatore di una cella riutilizzabile è il nome della sua classe, ma puoi cambiarlo in qualsiasi valore arbitrario. & Quot;

Ignorare -reuseIdentifer è rischioso. Cosa succede se si hanno due sottoclassi della sottoclasse della cella e si utilizzano entrambi in una vista tabella singola? Se inviano la chiamata dell'identificatore di riutilizzo su super, dovrai rimuovere una cella del tipo errato .............. Penso che devi sovrascrivere il metodo reuseIdentifier, ma devi restituire un identificatore soppiantato stringa. Oppure, se non ne è stato specificato uno, è necessario che restituisca la classe come stringa.

Per quello che vale, ho chiesto a un ingegnere iPhone di questo in uno dei Tech Tech Talk. La sua risposta fu: "Sì, è possibile utilizzare IB per creare celle. Ma non farlo. Per favore, non. & Quot;

Ho seguito le istruzioni di Apple come collegate da Ben Mosher (grazie!) ma ho scoperto che Apple ha omesso un punto importante. L'oggetto che progettano in IB è solo un UITableViewCell, così come la variabile che caricano da esso. Ma se in realtà lo si imposta come sottoclasse personalizzata di UITableViewCell e si scrivono i file di codice per la sottoclasse, è possibile scrivere dichiarazioni IBOutlet e metodi IBAction nel codice e collegarli ai propri elementi personalizzati in IB. Quindi non è necessario utilizzare i tag di visualizzazione per accedere a questi elementi e puoi creare qualsiasi tipo di cellula pazza che desideri. È il paradiso di Cocoa Touch.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top