2012-01-22 13 views
13

Podczas usuwania ostatniego rekordu z UITableView napotykam następujący błąd.UITableView deleteRowsAtIndexPath crash przy usuwaniu ostatniego rekordu

zakończenie aplikacji ze względu nieprzechwyconego wyjątkiem „NSInternalInconsistencyException”,: „powodu nieprawidłowych działka nieprawidłową liczbę wierszy w punkcie 0. Liczba wierszy zawartych w istniejącego odcinka po aktualizacji (3) może być równa liczbie wierszy znajdujących się w tej sekcji przed aktualizacją (1), plus lub minus liczba wierszy wstawionych lub usuniętych z tej sekcji (1 wstawiony, 1 usunięty) i plus lub minus liczba wierszy przeniesionych do lub z tej sekcji (0 wprowadzono, 0 przesunięto). "

Moim celem jest pokazanie "Brak rekordu", jeśli tablica tablicy jest pusta.

To jest kod, którego używam. Kiedy usuwam ostatni rekord z tablicy tablicowej, aplikacja ulega awarii. Jak można ponownie załadować tabelę i pokazać etykietę "Brak rekordu"?

// Customize the number of rows in the table view. 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    if ([idArray count]==0) { 
     return 3; 
    } 
    else 
    { 
     return [idArray count]; 
    } 
} 

// Customize the appearance of table view cells. 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    NSLog(@"array count %d",[idArray count]); 
    if ([idArray count] == 0) { 
     static NSString *CellIdentifier = @"Cell"; 

     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
     if (cell == nil) { 
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
     } 
     cell.textLabel.textAlignment = UITextAlignmentCenter; 

     tableView.userInteractionEnabled = NO; 

     self.navigationItem.leftBarButtonItem.enabled = NO; 
     NSUInteger row = [indexPath row]; 

     switch (row) { 
      case 0: 
       cell.textLabel.text = @""; 
       break; 
      case 1: 
       cell.textLabel.text = @""; 
       break; 

      case 2: 
       cell.textLabel.text = @"No Records Found"; 
       break; 


      default: 
       break; 
     }   

     return cell; 
    } 
    else 
    { static NSString *CellIdentifier = @"Cell"; 

     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
     if (cell == nil) { 
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; 
     } 

     tableView.userInteractionEnabled = YES; 

     self.navigationItem.leftBarButtonItem.enabled = YES; 

     // Set up the cell 
     identify *idItems = [idArray objectAtIndex:indexPath.row]; 

     NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 
     [formatter setDateFormat:@"dd MMM,yyyy"]; 
     NSString *dateStr = [formatter stringFromDate:idItems.Date]; 
     UIImageView *accDis = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Arrow.png"]];  
     cell.accessoryView = accDis; 
     self.idTableView.separatorColor = [UIColor colorWithRed:150.0/255.0 green:150.0/255.0 blue:150.0/255.0 alpha:1]; 
     cell.textLabel.textColor = [UIColor blackColor]; 
     cell.textLabel.font = [UIFont boldSystemFontOfSize:18]; 
     cell.textLabel.adjustsFontSizeToFitWidth = YES; 
     cell.detailTextLabel.textColor = [UIColor colorWithRed:100.0/255.0 green:100.0/255.0 blue:100.0/255.0 alpha:1]; 
     cell.detailTextLabel.font = [UIFont italicSystemFontOfSize:16]; 
     cell.detailTextLabel.adjustsFontSizeToFitWidth = YES; 

     NSString *detailText = [NSString stringWithFormat:@"%@ - %@",dateStr,idItems.GeoCode]; 

     if (idItems.Image == NULL) { 
      cell.imageView.image = [UIImage imageNamed:@"icon58x58.png"]; 
     } 
     else 
     { 
     //pass image to fix size 50 X 50 
     //UIImage *newImage = [self postProcessImage:idItems.Image]; 
      cell.imageView.image = idItems.thumb;//newImage; 
     cell.imageView.contentMode=UIViewContentModeScaleAspectFill; 
     } 

     cell.textLabel.text = idItems.TypeName; 
     cell.detailTextLabel.text = detailText; 

     return cell; 
    }  
} 

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

    if(editingStyle == UITableViewCellEditingStyleDelete) { 

     if ([idArray count] >=1) 
     { 
      [idTableView beginUpdates]; 

      //Get the object to delete from the array. 
      identifyObject = [appDelegate.idArray objectAtIndex:indexPath.row]; 

      //Delete the object from the table. 
      [self.idTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      [appDelegate removeID:identifyObject]; 

      if ([idArray count] == 0) { 
       [self.idTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      } 
      [idTableView endUpdates]; 
     } 
    } 
} 
+0

na którym linia Czy aplikacja katastrofę? jaki log konsoli? – sergio

+0

Crash logs proszę. - EDYCJA: ah, nie. Znalazłem to. –

+0

Dzięki Aktualizacja Crash log – Desmond

Odpowiedz

14

Problem polega na tym, że widok tabeli oczekuje operacji wykonywanych w widoku w celu dopasowania do źródła danych. Masz jeden rekord w tabeli i usuwasz go. Widok tabeli oczekuje, że źródło danych będzie teraz zawierało zero rekordów, ale z powodu logiki "brak rekordów znalezionych" zwraca wartość 3, stąd błąd spójności i awarię.

Błąd wydaje się być ta część:

if ([idArray count] == 0) { 
    [self.idTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
} 

Zakładam ten był przeznaczony do wstawienia „nie znaleziono” wiersz do tabeli, gdy ostatnia linia zostanie usunięta, ale od twoich „nie znaleziono "w rzeczywistości obejmuje trzy wiersze, trzeba wstawić trzy rzędy tutaj zamiast, jak to:

if ([idArray count] == 0) { 
    [self.idTableView insertRowsAtIndexPaths:[NSArray arrayWithObjects: 
    [NSIndexPath indexPathForRow:0 inSection:indexPath.section], 
    [NSIndexPath indexPathForRow:1 inSection:indexPath.section], 
    [NSIndexPath indexPathForRow:2 inSection:indexPath.section], 
    nil] withRowAnimation:UITableViewRowAnimationFade]; 
} 

na jesteś właścicielem poczytalności jednak mogę zaproponować inne podejście? Zamiast próbować zsynchronizować tabelę i źródło danych podczas żonglowania tymi fałszywymi trzema rzędami danych, które są tam tylko w celach wyświetlania, może po prostu wstawić UILabel do hierarchii widoku (przed lub za widokiem tabeli), która mówi: " nie znaleziono rekordów "i pokazać/ukryć na podstawie tego, czy w tabeli są jakieś dane? W ten sposób możesz precyzyjnie kontrolować swoją pozycję i wygląd bez konieczności wkręcania w logikę źródła danych.

+0

Dzięki, nicku. Spróbuję wypuścić – Desmond

+0

Więc ... czy to działa? –

+0

działa w pewnym zakresie, ostatni wiersz został usunięty ... ale pokazuje zabawny błąd. W końcu przyjmuję radę, aby pokazać i UILabel dla żadnego rekordu znalezionego. – Desmond

10

Ogólne zasady postępowania z usuwanie wierszy to:

  1. czynienia z modelem
  2. Deal z ROW w animacji

Tak na przykład:

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

    if (editingStyle == UITableViewCellEditingStyleDelete) { 
     NSInteger row = [indexPath row]; 

     [yourModel removeObjectAtIndex:row]; // you need to update your model 

     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
    } 
} 

Teraz, w moim zdaniem poprawny kod może być następujący (napisałem kilka komentarzy, aby Cię poprowadzić).

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

    if (editingStyle == UITableViewCellEditingStyleDelete) { 
     //Get the object to delete from the array. 
     identifyObject = [appDelegate.idArray objectAtIndex:indexPath.row]; 
     [appDelegate removeID:identifyObject]; // update model first 

     // now you can check model count and do what you want 
     if ([appDelegate.idArray count] == 0) // I think you mean appDelegate.idArray 
     { 
      // do what you want 
      // with [self.idTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     } 

     else 
     { 
      [self.idTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     } 
    } 
} 

Mam nadzieję, że to pomaga.

2

Użyłem tej samej metody, w której użyłem komórki do ostrzeżenia "Brak wierszy".

Dla mnie to działało:

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

if (editingStyle == UITableViewCellEditingStyleDelete) { 

    [favs removeObjectAtIndex:indexPath.section]; 

    if ([favs count] == 0) { 
     [tableView reloadRowsAtIndexPaths:[[NSArray alloc]initWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade]; 
     [tableView setEditing:NO animated:YES]; 

     // Remove Edit bar button item 
     self.navigationItem.rightBarButtonItem = nil; 
    } 
    else { 
     // Animate the deletion from the table. 
     [tableView deleteRowsAtIndexPaths:[[NSArray alloc]initWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade]; 
    } 
} 

}

+0

Dzięki, zadziałało mi pięknie ... –

Powiązane problemy