2011-03-28 14 views
15

Cuando tengo datos en mi UITableView y comienzo a eliminar, funciona bien. Sin embargo, cuando llego al último objeto de la tabla y lo elimino, se cuelga.NSInternalInconsistencyException (número inválido de filas)

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted).'

Así es como que estoy haciendo las cosas de edición:

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (editingStyle == UITableViewCellEditingStyleDelete) { 
     // Delete the row from the data source 
     if ([myData count] >= 1) { 
      [tableView beginUpdates]; 
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      [myData removeObjectAtIndex:[indexPath row]]; 

      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
      NSString *documentsDirectory = [paths objectAtIndex:0]; 
      NSString *somepath = [documentsDirectory stringByAppendingPathComponent:@"something.plist"]; 
      [myData writeToFile:somepath atomically:YES]; 
      [table reloadData]; 
      if ([myData count] == 0) { 
       [tableView endUpdates]; 
       [tableView reloadData]; 
      } 
      else { 
      [tableView endUpdates]; 
      } 
     } 
    } 
} 

Y también esto:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    // Return the number of rows in the section. 
    if ([myData count] != 0) { 
     return [myData count]; 
    } 
    else { 
     return 1; 
    } 
} 

La razón por la que estoy devolviendo 1 se debe a que estoy haciendo una celda que dice "Sin datos guardados" en cellForRowAtIndexPath. Esto es lo que quiero decir:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    }  
    if ([cityData count] != 0) { 
     //normal setup removed for clarity 
    } 
    else { 
     cell.textLabel.text = @"No saved data!"; 
    cell.textLabel.font = [UIFont boldSystemFontOfSize:14]; 
    cell.textLabel.textAlignment = UITextAlignmentCenter; 
    cell.selectionStyle = UITableViewCellSelectionStyleNone; 
     cell.tag = 1; 
    return cell; 
    } 
} 

Entonces, ¿qué estoy haciendo mal en mi código de edición para obtener este error? ¡Gracias!

Respuesta

28

Si elimina la última fila de su tabla, el código UITableView espera que haya 0 filas restantes. Llama a sus métodos UITableViewDataSource para determinar cuántos quedan. Como tiene una celda "Sin datos", devuelve 1, no 0. Por lo tanto, cuando elimine la última fila de su tabla, intente llamar al -insertRowsAtIndexPaths:withRowAnimation: para insertar su fila "Sin datos". Además, no debe llamar al -reloadData en ningún lugar de este método. -endUpdates se encargará de volver a cargar las filas afectadas. Trate de hacer esto:

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (editingStyle == UITableViewCellEditingStyleDelete) { 
     // Delete the row from the data source 
     if ([myData count] >= 1) { 
      [tableView beginUpdates]; 
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      [myData removeObjectAtIndex:[indexPath row]]; 

      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
      NSString *documentsDirectory = [paths objectAtIndex:0]; 
      NSString *somepath = [documentsDirectory stringByAppendingPathComponent:@"something.plist"]; 
      [myData writeToFile:somepath atomically:YES]; 

      if ([myData count] == 0) { 
       [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      } 
      [tableView endUpdates]; 
     } 
    } 
} 
+1

Perfecto, ¡gracias! –

+3

Lo que también puede hacer es llamar a tableView deleteRowsAtIndexPaths si [data count]> 0 y luego DO llama a reloadData. De esta manera no borras la última celda si se va a usar para una celda "sin datos" y la recarga hace que el delegado cargue la información correcta en la tabla vista. – EeKay

+0

¡Gracias, eso también me ayudó! –

1

retire primero de myData y luego eliminar de tableview.

-(void)tableView:(UITableView *)tableView commitEditingStyle: 
(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 

if (editingStyle == UITableViewCellEditingStyleDelete) { 
     //somehting... 
     [myData removeObjectAtIndex:[indexPath row]]; 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     //somehting... 
    } 
} 

}

1

El método tableView:numberOfRowsInSection siempre debe devolver número exacto de filas:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    // Return the number of rows in the section. 
    return [myData count]; 
} 

Después de haber eliminado la última fila, es posible que desee eliminar toda la sección. Simplemente llame al deleteSections:withRowAnimation: dentro de un bloque beginUpdates y endUpdated;

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (editingStyle == UITableViewCellEditingStyleDelete) { 
     // Delete the row from the data source 
     [tableView beginUpdates]; 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     [myData removeObjectAtIndex:[indexPath row]]; 
     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
     NSString *documentsDirectory = [paths objectAtIndex:0]; 
     NSString *somepath = [documentsDirectory stringByAppendingPathComponent:@"something.plist"]; 
     [myData writeToFile:somepath atomically:YES]; 
     if ([myData count] == 0) { 
      // NEW! DELETE SECTION IF NO MORE ROWS! 
      [tableView deleteSections:[NSIndexSet indexSetWithIndex:[indexPath section]] withRowAnimation:UITableViewRowAnimationFade]; 
     } 
     [tableView endUpdates]; 
    } 
} 
Cuestiones relacionadas