Pregunta

Puedo diseñar UITableViewCells personalizados y cargarlos bien usando la técnica descrita en el hilo que se encuentra en http://forums.macrumors.com/showthread.php?t=545061 . Sin embargo, el uso de ese método ya no le permite iniciar la celda con un reuseIdentifier, lo que significa que debe crear instancias completamente nuevas de cada celda en cada llamada. ¿Alguien ha descubierto una buena manera de almacenar en caché determinados tipos de células para reutilizarlos, pero aún así poder diseñarlos en Interface Builder?

¿Fue útil?

Solución

Simplemente implemente un método con la firma del método apropiado:

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

Otros consejos

En realidad, ya que está construyendo la celda en el Interface Builder, simplemente configure el identificador de reutilización allí:

 IB_reuse_identifier

O si está ejecutando Xcode 4, verifique la pestaña del inspector de atributos:

ingrese la descripción de la imagen aquí

(Editar: Una vez que XC es generado por XCode, contiene un UIView vacío, pero necesitamos un UITableViewCell, por lo que debe eliminar manualmente el UIView e insertar una celda de vista de tabla. Por supuesto, IB no mostrará ningún UITableViewCell parámetros para una UIView.)

Ahora, en iOS 5 hay un método UITableView apropiado para eso:

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

No recuerdo dónde encontré este código originalmente, pero hasta ahora me ha funcionado muy bien.

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

Ejemplo de configuración de Interface Builder ...

 texto alternativo

Mira la respuesta que di a esta pregunta:

¿Es posible diseñar subclases de NSCell en la interfaz? ¿Constructor?

No solo es posible diseñar un UITableViewCell en IB, es deseable porque, de lo contrario, todo el cableado manual y la colocación de múltiples elementos es muy tedioso. El rendimiento está bien siempre y cuando tenga cuidado de hacer que todos los elementos sean opacos cuando sea posible. El ID de reutilización se establece en IB para las propiedades del UITableViewCell, luego se usa el ID de reutilización correspondiente en el código cuando se intenta sacar de la cola.

También escuché de algunos de los presentadores en WWDC el año pasado que no debería hacer celdas de vista de tabla en IB, pero es una carga de literas.

A partir de iOS aproximadamente 4.0, hay instrucciones específicas en los documentos de iOS que hacen que este trabajo sea súper rápido:

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

Desplácese hacia abajo hasta donde se habla de subclases de UITableViewCell.

Aquí hay otra opción:

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 mis celdas de vista personalizada de una manera similar, excepto que conecto la celda a través de un IBOutlet.

El enfoque [nib objectAt ...] es susceptible de cambios en las posiciones de los elementos en la matriz.

El enfoque de UIViewController es bueno, solo lo probé y funciona lo suficientemente bien.

PERO ...

En todos los casos, no se llama al constructor initWithStyle , por lo que no se realiza la inicialización predeterminada.

He leído varios lugares sobre el uso de initWithCoder o awakeFromNib , pero no hay evidencia concluyente de que alguno de estos sea el camino correcto.

Aparte de llamar explícitamente a algún método de inicialización en el método cellForRowAtIndexPath , aún no he encontrado una respuesta a esto.

Hace un tiempo encontré una excelente publicación de blog sobre este tema en blog.atebits.com , y desde entonces he comenzado a usar la clase ABTableViewCell de Loren Brichter para hacer todas mis UITableViewCells.

Terminas con un simple contenedor UIView para colocar todos tus widgets, y el desplazamiento es muy rápido.

Espero que esto sea útil.

Esta técnica también funciona y no requiere un ivar funky en el controlador de vista para la administración de la memoria. Aquí, la celda de vista de tabla personalizada vive en un xib denominado " 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];
  }

El método de Louis funcionó para mí. Este es el código que utilizo para crear el UITableViewCell desde la punta:

- (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 solución de gustavogb no me funciona, lo que intenté es:

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

Parece que funciona. El blogTableViewCell es el IBOutlet para la celda y ChainesController es el propietario del archivo.

De los documentos de UITableView relativos a dequeueWithReuseIdentifier : " Una cadena que identifica el objeto de celda que se va a reutilizar. De forma predeterminada, el identificador de una celda reutilizable es su nombre de clase, pero puede cambiarlo a cualquier valor arbitrario. & Quot;

Reemplazar -reuseIdentifer usted mismo es arriesgado. ¿Qué sucede si tiene dos subclases de su subclase de celda y utiliza ambas en una sola vista de tabla? Si envían la llamada del identificador de reutilización a super, sacará de la cola una celda del tipo incorrecto .............. Creo que debe reemplazar el método reuseIdentifier, pero debe devolver un identificador suplantado cuerda. O, si no se ha especificado uno, haga que devuelva la clase como una cadena.

Para lo que vale, le pregunté a un ingeniero de iPhone acerca de esto en una de las charlas tecnológicas del iPhone. Su respuesta fue: "Sí, es posible usar IB para crear celdas". Pero no lo hagas Por favor, no lo hagas. & Quot;

Seguí las instrucciones de Apple según lo vinculado por Ben Mosher (¡gracias!) pero encontré que Apple omitió un punto importante. El objeto que diseñan en IB es solo un UITableViewCell, al igual que la variable que cargan de él. Pero si realmente lo configura como una subclase personalizada de UITableViewCell, y escribe los archivos de código para la subclase, puede escribir declaraciones de IBOutlet y métodos IBAction en el código y conectarlos a sus elementos personalizados en IB. Entonces no es necesario usar etiquetas de vista para acceder a estos elementos y puede crear cualquier tipo de celda loca que desee. Es el cielo de Cocoa Touch.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top