2009-02-20 16 views
7

Estoy leyendo una celda de tabla personalizada en tableView:cellForRowAtIndexPath: desde un archivo de punta. Esto funciona muy bien para mis propósitos, excepto que es bastante lento.Copiando UITableViewCell

Ahora, sé que lo correcto a largo plazo es crear la celda completamente en código y usar una sola vista, y así sucesivamente. Pero este es un prototipo, y no quiero poner tanto esfuerzo en ello.

Por ahora, me alegraría si estuviera leyendo la punta una sola vez en la subclase UIViewController, luego tableView:cellForRowAtIndexPath: hizo copias de la misma. Mi suposición aquí es que copiar sería más rápido que leer el plumín.

Esto es lo que utilizo para cargar la punta, que llamo de viewDidLoad: (y después de retain)

-(id)loadFromNamed:(NSString*)name { 
    NSArray *objectsInNib = [[NSBundle mainBundle] loadNibNamed:name 
                  owner:self 
                 options:nil]; 
    assert(objectsInNib.count == 1); 
    return [objectsInNib objectAtIndex:0]; 
} 

Todo está bien hasta ahora. Pero la pregunta es: ¿cómo copio esto una y otra vez? ¿Es posible?

Probé [_cachedObject copy] y [_cachedObject mutableCopy] pero UITableViewCell no es compatible con ninguno de los protocolos de copiado.

Si tengo que hacerlo, puedo decirles que ignoren la velocidad hasta que esté preparado para quitar la punta por completo, pero prefiero que funcione un poco más rápido si hay una fruta que cuelga aquí.

¿Alguna idea?

Respuesta

6

Utilice la clonación de célula integrada en la vista de tabla. Apple sabía que generar muchas células de tabla era lento. Echa un vistazo a los documentos para este método:

- (UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier 

Se crea la célula una vez, entonces como se solicitan nuevas células, utiliza este método para clonar las células existentes. Luego solo cambia lo que necesita cambiarse sobre la nueva celda y devuelve el objeto de celda.

También consulte la vista de tabla del código de muestra proporcionado por Apple que utiliza este método y le muestra el camino correcto. El hecho de que tu celda fue cargada desde una punta no debería importar en absoluto.


Clarificación menor: no creo que el método anterior clone células para usted. En su lugar, se necesita un objeto de celda que se haya desplazado de la pantalla y simplemente los mueva a un lugar nuevo. Entonces, literalmente, está reutilizando una celda. Por lo tanto, asegúrese de que la vista de tabla personalizada se pueda establecer en todos los valores nuevos que necesite fuera de la inicialización.

+0

Gracias. Me había olvidado de 'dequeueReusableCellWithIdentifier'. Ahora lo estoy usando, pero aún es más lento de lo que me gustaría. Eso sugiere que el cuello de botella está en el dibujo, que tendrá que esperar hasta que tenga tiempo para aplicar los otros trucos rápidos de la mesa. ¡Pero ahora sé lo que está pasando! –

+0

Bueno, su enfoque habría sido incluso más lento ya que la reutilización de objetos es mucho más rápida que la clonación de objetos. Me alegro de poder ayudar. –

+0

Probar perfiles en el dispositivo para ver con certeza lo que se está ejecutando lentamente. Algunas personas dicen que el truco es usar solo una vista por celda y hacer todo tu propio dibujo. –

3

Bueno, no estoy seguro de por qué todos los tutoriales no especifican este paso.

Al usar su propio UITableViewCell desde Nib, no es suficiente llamar a dequeueReusableCellWithIdentifier. Debe especificar el "Identificador" en el IB, solo para ello en la sección de la pestaña Celda de vista de tabla.

Luego, asegúrese de que el identificador que coloca en IB es el mismo que el identificador que utiliza para el dequeueReusableCellWithIdentifier.

4

No orgullosos de esta solución, pero funciona con el máximo número de posibles enlaces de IB:

Interface (AlbumTableViewCell es una subclase de UITableViewCell de las cuales una instancia se define en el archivo XI ter del AlbumViewController):

@interface AlbumsViewController : UITableViewController { 
    IBOutlet AlbumTableViewCell *tableViewCellTrack; 
} 

@property (nonatomic, retain) AlbumTableViewCell *tableViewCellTrack; 

implementación (desarchivar/archivo hace una célula de la vista de tabla copiar/clones):

@implementation AlbumsViewController 

@synthesize tableViewCellTrack; 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    AlbumTableViewCell *cell = (AlbumTableViewCell *)[tableView dequeueReusableCellWithIdentifier: @"AlbumCell"]; 

    if (cell == nil) { 
     AlbumsViewController *albumsViewController = [[[AlbumsViewController alloc] init] autorelease]; 
     [[NSBundle mainBundle] loadNibNamed: @"AlbumsViewController" owner: albumsViewController options: nil]; 

     cell = albumsViewController.tableViewCellTrack; 
    } 

    cell.labelTitle.text = ...; 
    cell.labelArtist.text = ...; 

    return cell; 
} 
8

Creo que hacer frente de la tabla cel Puedo usarlo junto con un mecanismo de dequeueing, que permitirá crear células una vez (desde el pico o programáticamente o cargarlo automáticamente desde otro plumín y unirlo como una salida en IB) y luego clonarlo o dequearlo cuando sea necesario.

UITableViewCell no se ajusta al protocolo NSCopying, pero es compatible con el mecanismo de archivado/desarchivo con clave, por lo que se puede usar para la clonación.

Basado en respuesta " How to duplicate a UIButton in Objective C?" mi método delegado fuente de datos se parece a:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *CellID = @"CellIdentifier"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID]; 

    if (!cell) { 
     NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject:self.tableViewCell]; 
     cell = [NSKeyedUnarchiver unarchiveObjectWithData:archivedData]; 
    } 

    // ... config ... 

    return cell; 
} 

Y en mi caso self.tableViewCell es una célula que se ha cargado una sola vez desde el archivo punta de vista.

No probé lo que será más rápido: "archivo + desarchivar" para clonar o "archivo de punta de carga + desarchivar" qué marco va a hacer en caso de -loadNibNamed: Propietario: Opciones:, que utilizan este método solo con consideraciones de conveniencia, pero hay buenas posibilidades de que la operación de la memoria frente a la operación del archivo sea más rápida.

EDITAR: Parece que no es tan fácil como parecía al principio. Como UIImage no se ajusta a NSCoding, las células con UIImageViews configuradas no se pueden copiar simplemente sin código adicional. Sí, copiar una imagen completa definitivamente no es una buena práctica, aclama a Apple por señalar esto.

+0

Wow Nunca hubiera averiguado cómo duplicar una UITableViewCell si no fuera por esta publicación. Muchas gracias. –

+0

restricciones no lograron archivar/desarchivar :-( –

1

Aquí está en Swift

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    var cell : UITableViewCell? 
    let cellId = String(format: "Cell%d", indexPath.row) 
    cell = alertTable!.dequeueReusableCellWithIdentifier(cellId) as! UITableViewCell? 

    if cell == nil { 
     let archivedData = NSKeyedArchiver.archivedDataWithRootObject(masterTableCell!) 
     cell = NSKeyedUnarchiver.unarchiveObjectWithData(archivedData) as! UITableViewCell? 
    } 

    // do some stuff 

    return cell! 
}