Configurar el estilo de UITableViewCell al usar iOS 6 UITableView dequeueReusableCellWithIdentifier: forIndexPath:


Estoy tratando de averiguar cómo establecer el UITableViewCellStyle cuando se utilizan los nuevos métodos en iOS 6 para UITableView.

Anteriormente, al crear un UITableViewCell cambiaría la enumeración UITableViewCellStyle para crear diferentes tipos de celdas predeterminadas al llamar a initWithStyle:, pero por lo que puedo recopilar, este ya no es el caso.

La documentación de Apple para UITableView establece:

Valor de retorno : Un objeto UITableViewCell con el identificador de reutilización asociado. Este método siempre devuelve un valor válido celular.

Debate : Por razones de rendimiento, el origen de datos de una vista de tabla generalmente debe reutilizar los objetos UITableViewCell cuando asigna celdas a filas en su método tableView:cellForRowAtIndexPath:. Una vista de tabla mantiene una cola o lista de objetos UITableViewCell que el origen de datos ha marcado para su reutilización. Llame a este método desde su objeto de origen de datos cuando se le pida que proporcione una nueva celda para la vista de tabla. Este método desactiva una celda existente si hay una disponible o crea uno nuevo basado en la clase o el archivo nib que registraste anteriormente.

Importante : Debe registrar una clase o archivo nib usando el método registerNib:forCellReuseIdentifier: o registerClass:forCellReuseIdentifier: antes de llamar a este método.

Si ha registrado una clase para el identificador especificado y se debe crear una nueva celda, este método inicializa la celda llamando a su método initWithStyle:reuseIdentifier:. Para las células basadas en nib, esto el método carga el objeto cell desde el archivo nib proporcionado. Si una celda existente estaba disponible para su reutilización, este método llama al método prepareForReuse de la celda en su lugar.

Así es como mi nuevo cellForRowAtIndexPath se ve después de implementar los nuevos métodos:

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

El código que tengo hasta ahora funciona bien, pero siempre devuelve el estilo predeterminado. ¿Cómo puedo cambiar esto para que pueda crear celdas con otros estilos como UITableViewCellStyleDefault, UITableViewCellStyleValue1, UITableViewCellStyleValue2 y UITableViewCellStyleSubtitle?

No quiero subclase UITableViewCell, yo solo quiero cambiar el tipo predeterminado como podría hacer antes de iOS 6. Parece extraño que Apple proporcionara métodos mejorados pero con una documentación mínima para respaldar su implementación.

¿Alguien ha dominado esto, o se ha topado con un problema similar? Estoy luchando para encontrar cualquier información razonable en absoluto.

Author: CaptainRedmuff, 2012-11-01

6 answers

Sé que dijiste que no querías crear una subclase, pero parece inevitable. Basado en el código de ensamblado durante las pruebas en el simulador de iOS 6.0, UITableView crea nuevas instancias de UITableViewCell (o sus subclases) realizando

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

En otras palabras, el estilo enviado (UITableViewCellStyleDefault) parece estar codificado. Para evitar esto, necesitará crear una subclase que anule el inicializador predeterminado initWithStyle:reuseIdentifier: y pase el estilo que desea usar:

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

También, podría ser mejor enviar registerClass:forCellReuseIdentifier: en viewDidLoad, en lugar de hacerlo cada vez que se solicita una celda:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerClass:<RegisteredClass> forCellReuseIdentifier:<ReuseIdentifier>];
}
 104
Author: bolot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-02 12:38:54

dequeueReusableCellWithIdentifier no está en desuso, por lo que no es necesario usar el nuevo dequeueReusableCellWithIdentifier:forIndexPath:.

Use la nueva forma junto con el método de registro apropiado (en viewDidLoad) si está utilizando una clase de celda personalizada, pero use la forma antigua si desea usar una de las enumeraciones UITableViewCellStyle.

 60
Author: Murray Sagal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-22 17:21:18

Puede evitar una subclase extraña utilizando el generador de interfaz de storyboard:

  1. En la vista Storyboard, seleccione la celda prototipo de celda de vista de tabla (en la vista de tabla)
  2. En la vista Utilidades, en el inspector de atributos, modifique el valor de estilo
  3. (Opcionalmente) Modificar otros valores como Selección y Accesorio

El nuevo iOS 6.0 dequeueReusableCellWithIdentifier:forIndexPath: utiliza esos valores al asignar nuevas celdas y devolverlas. (Probado en una compilación de iOS 6.0 usando Xcode 4.5.2)

 11
Author: Jeff Collier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-11 02:16:07

Otra alternativa que guarda un archivo es crear un Nib y usar registerNib:forCellReuseIdentifier: en su lugar.

Hacer el plumín es fácil: Crear un nuevo.archivo xib en Interface Builder. Eliminar la vista predeterminada. Agregar un objeto de celda de vista de tabla. Usando el Inspector de atributos, cambie el estilo de la celda. (Aquí también tiene la oportunidad de personalizar aún más la celda ajustando otros atributos.)

Luego, en el método viewDidLoad de su controlador de vista de tabla, llame a algo como:

[self.tableView registerNib:[UINib nibWithNibName:@"StyleSubtitleTableCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"Cell"];
 7
Author: Mr. Berna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-18 17:58:55

La respuesta de Bolot es la correcta. Simple y no necesita crear ningún archivo XIB.

Solo quería actualizar su respuesta para quienquiera que lo esté haciendo usando Swift en lugar de 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")
}
 0
Author: Gabriel Oliva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-15 14:40:26

Mi solución a esto es llamar a initWithStyle: reuseIdentifier: después de haberlo obtenido usando [self.tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath]. Después de todo, init es solo otro selector, y el compilador no hace restricciones a llamarlo en un objeto ya inicializado. Sin embargo, se quejará de no usar el resultado de llamar a init, así que lo hago:

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

Me imagino que esto no funcionará en Swift...

 -5
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-11 08:17:40