Die Fehlermeldung 'Ungültiges update: ungültige Anzahl von Zeilen im Abschnitt 0" versuchen zu löschen, Zeile in Tabelle
Mein code scheint zu laufen just fine aber, wenn ich swipe, um eine Zeile zu löschen, die in meiner UITableView, stürzt die app mit den folgenden:
Fehler
LittleToDoApp[70390:4116002] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Ungültiges update: ungültige Anzahl von Zeilen im Abschnitt 0. Die Anzahl der Zeilen, die in einer bestehenden Abschnitt nach dem update (1) muss gleich sein der Anzahl der Zeilen in diesem Abschnitt, bevor Sie das update (1), plus oder minus die Anzahl der Zeilen, die eingefügt oder gelöscht, der Abschnitt (0 eingefügt, 1 gestrichen) und plus oder minus die Anzahl der Zeilen bewegt, die in oder aus diesem Abschnitt (0 verschoben, 0 verschoben).'
ViewController.m
#import "ViewController.h"
#import "ToDoItem.h"
#import "ToDoItemSvcCache.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize tableView;
ToDoItemSvcCache *ToDoItemSvc = nil;
- (void)viewDidLoad
{
[super viewDidLoad];
//Do any additional setup after loading the view, typically from a nib.
ToDoItemSvc = [[ToDoItemSvcCache alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
//Dispose of any resources that can be recreated.
}
- (IBAction)deleteToDoItem:(id)sender {
NSLog(@"Deleting ToDoItem");
[self.view endEditing:YES];
}
- (IBAction)addToDoItem:(id)sender {
[self.view endEditing:YES];
NSLog(@"saveToDoItem: entering");
ToDoItem *todoitem = [[ToDoItem alloc] init];
todoitem.todoitem = _toDoItem.text;
[ToDoItemSvc createToDoItem:todoitem];
[self.tableView reloadData];
NSLog(@"saveToDoItem: todoitem saved");
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = @"toDoItemCell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:simpleTableIdentifier];
}
ToDoItem *toDoItem = [[ToDoItemSvc retrieveAllToDoItems]
objectAtIndex:indexPath.row];
cell.textLabel.text = [toDoItem description];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [[ToDoItemSvc retrieveAllToDoItems] count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"viewToDoItem"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
SecondViewController *destViewController = segue.destinationViewController;
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
destViewController.toDoItemName = cell.textLabel.text;
}
}
#pragma hiding status bar
- (BOOL)prefersStatusBarHidden {
return YES;
}
//here we get back from both styles
- (IBAction)unwindFromDetailViewController:(UIStoryboardSegue *)segue
{
//UIViewController *detailViewController = [segue sourceViewController];
NSLog(@"%@", segue.identifier);
}
//Allows the delete button to show up when left swipping a list item
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
//Return YES - we will be able to delete all rows
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
//Will add code to actually delete a row here. Adding NSLog so we know its triggering though
NSLog(@"Deleted row.");
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView reloadData];
}
@end
ToDoItemSvc.h
#import <Foundation/Foundation.h>
#import "ToDoItem.h"
@protocol ToDoItemSvc <NSObject>
- (ToDoItem *) createToDoItem: (ToDoItem *) todoitem;
- (NSMutableArray *) retrieveAllToDoItems;
- (ToDoItem *) updateToDoItem: (ToDoItem *) todoitem;
- (ToDoItem *) deleteToDoItem: (ToDoItem *) todoitem;
@end
Vollständige Quelle
https://github.com/martylavender/LittleToDoApp/tree/Storyboards
Bearbeiten
Folgenden nach der Bemerkung/s von Fennelouski, sollte ich etwas in dieser Richtung?
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.toDoItem removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView reloadData];
}
}
Edit 2
Dies ist, was ich immer bin:
https://www.evernote.com/l/AJiah58lVhdGXIYO1F5yv6fJXc7k3WjRLNYB/image.png
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Anzahl der Zeilen in der Tabelle ist
[[ToDoItemSvc retrieveAllToDoItems] count]
. Wenn Sie löschen1
Zeile in der Tabelle dann die Anzahl der Zeilen in der Tabelle sein sollten1
weniger als die Anzahl der Zeilen vor dem löschen alle Zeilen. Nach dem löschen1
Zeile und rufen Sie[self.tableView reloadData]
tableView überprüft, um zu sehen, wie viele Zeilen es gibt in der Tabelle. An dieser StellenumberOfRowsInSection
zurück[[ToDoItemSvc retrieveAllToDoItems] count]
. Dies sollte jetzt1
weniger, als es war, bevor Sie gelöscht wird eine Zeile.Die kurze Antwort ist, müssen Sie zuerst entfernen Sie ein Element aus der Datenquelle, die zu sein scheint
[ToDoItemSvc retrieveAllToDoItems]
dann eine Zeile löschen.Kompliment ist, wenn Sie eine Zeile hinzufügen, müssen Sie fügen Sie ein Element zu Ihrer Datenquelle sowie.
Diese Veränderungen müssen geschehen, bevor Sie rufen
reloadData
.Bearbeiten
ELI5: EIN Lehrer hat fünf Studenten: Alice, Bob, Charlie, Diane und Eric. Bob ' s Mutter holt ihn frühzeitig von der Schule vor dem Mittagessen. Nach dem Mittagessen nimmt der Lehrer die Anwesenheit und die Panik, denn er hat nur vier Kinder, wenn die Liste sagt, es sollten fünf sein. Wo ist Bob?!
Wenn Bob ' s Mutter hatte sich entfernt, sein name aus der Liste, wenn Sie nahm ihn aus der Schule und der Lehrer würde nicht in Panik.
[ToDoItemSvc deleteToDoItem:[ToDoItemSvc retrieveAllToDoItems][indexPath.row]]
vor Ihrem Anruf aufdeleteRowsAtIndexPaths
. Sie brauchen auch nicht anzurufenreloadData
danach.Habe ich es herausgefunden mit der Hilfe von oben, und einige denken.
Zuerst, ich bin fertig mit der tatsächlichen deleteToDoItem code
Dann den obigen code
Läuft und mir erlaubt zu löschen, meine Sache wie ich will!!!!