2009-09-24 8 views
32

Me gustaría que mi UITableView se comporte como la tabla en el editor de contactos, es decir, el usuario debería presionar Editar y una fila de "agregar nueva categoría" debería aparecer en la parte inferior de cada sección.Usar filas de inserción en una UITableView

Estoy usando el siguiente código para hacer esto, pero el problema es que no hay una transición suave como la que hay en Contactos. En cambio, la nueva fila aparece de repente. ¿Cómo puedo obtener la animación?

Además, ¿cómo respondo a los clics en la fila "agregar nueva categoría"? La fila no se puede hacer clic en mi implementación actual.

¿Debo volver a cargar los datos cuando el usuario comienza a editarlos? Estoy haciendo esto porque de lo contrario las filas de inserción nunca se dibujan.

Gracias.

- (void)setEditing:(BOOL)editing animated:(BOOL)animated { 
    [super setEditing:editing animated:animated]; 
    [self.tableView setEditing:editing animated:animated]; 
    [tableView reloadData]; 
} 

- (NSInteger)tableView:(UITableView *)_tableView numberOfRowsInSection:(NSInteger)section { 
    // ... 
    if(self.tableView.editing) 
     return 1 + rowCount; 
} 

- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    // ..... 
    NSArray* items = ...; 
    if(indexPath.row >= [items count]) { 
     cell.textLabel.text = @"add new category"; 
    } 
    // ... 

    return cell; 
} 

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSArray* items = ...; 

    if(indexPath.row == [items count]) 
     return UITableViewCellEditingStyleInsert; 

    return UITableViewCellEditingStyleDelete; 
} 
+2

Esto era muy útil (junto con la respuesta, más adelante). Solo una inconsistencia menor: la comparación con el conteo de filas en 'tableView: cellForRowAtIndexPath:' usa '> =' mientras que la de 'tableView: editingStyleForRowAtIndexPath:' usa '=='. No es gran cosa, pero debería ser consistente entre ellos. '> =' cubriría cualquier doble adición accidental de la fila Insertar, mientras que '==' ayudaría lanzando una excepción por cualquier error de código que pudiera llevar a esa situación. –

Respuesta

36

Me faltaba una cosa. En setEditing :, en lugar de llamar reloadData que debería haber hecho:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated { 
    [super setEditing:editing animated:animated]; 
    [self.tableView setEditing:editing animated:animated]; // not needed if super is a UITableViewController 

    NSMutableArray* paths = [[NSMutableArray alloc] init]; 

    // fill paths of insertion rows here 

    if(editing) 
     [self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom]; 
    else 
     [self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom]; 

    [paths release]; 
} 
+3

Gracias Bill, esto fue muy útil para mí. Pasé varias horas rebuscando en un código similar, pero no pude hacerlo del todo bien. Esto ayudó muchísimo. – hkatz

+0

¡Me alegro de que haya sido útil! – Bill

+0

¿qué pasa con commitEditingStyle: forRowAtIndexPath? La documentación de Apple dice que se llama a setEditing cuando la vista de tabla entra por primera vez en el modo de edición ... ¿Cómo sabría qué filas insertar/eliminar en ese punto? – shim

5

En respuesta a los clics en la fila se podría hacer en el método didSelectRowAtIndexPath, por indexPath.row == [items count]. Para la animación, sugiero echar un vistazo here, en el método insertRowsAtIndexPaths:withRowAnimation:. Hay una publicación sobre cómo usarlo here.

0

Un efecto secundario no deseado de la solución destacar es que el "add" se inserta la fila también cuando el usuario simplemente desliza una sola fila (siempre que deslizar está habilitado). El siguiente código resuelve este dilema:

// Assuming swipeMode is a BOOL property in the class extension. 

- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // Invoked only when swiping, not when pressing the Edit button. 
    self.swipeMode = YES; 
} 

- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    self.swipeMode = NO; 
} 

Su código requeriría un pequeño cambio:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated { 
    [super setEditing:editing animated:animated]; 
    [self.tableView setEditing:editing animated:animated]; // not needed if super is a UITableViewController 

    if (!self.swipeMode) { 

     NSMutableArray* paths = [[NSMutableArray alloc] init]; 

     // fill paths of insertion rows here 

     if(editing) 
      [self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom]; 
     else 
      [self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationBottom]; 
     [paths release]; 
    } 
} 
Cuestiones relacionadas