我的代码似乎运行得很好但是当我滑动以删除我的UITableView中的一行时,该应用程序崩溃了以下内容:
LittleToDoApp [70390:4116002] ***由于未捕获的异常终止应用程序' NSInternalInconsistencyException',原因:'无效更新:第0部分中的行数无效。包含的行数更新后的现有部分(1)必须等于更新前的该部分中包含的行数(1),加上或减去从该部分插入或删除的行数(0插入,1删除)和加号或减去移入或移出该部分的行数(0移入,0移出)。'
#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
#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
https://github.com/martylavender/LittleToDoApp/tree/Storyboards
在Fennelouski发表评论后跟进,我是否应该沿着这些方向做点什么?
- (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];
}
}
这就是我得到的:
https://www.evernote.com/l/AJiah58lVhdGXIYO1F5yv6fJXc7k3WjRLNYB/image.png
答案 0 :(得分:20)
表格中的行数为[[ToDoItemSvc retrieveAllToDoItems] count]
。当您删除表中的1
行时,表中的行数应该比删除任何行之前的行数少1
。删除1
行并调用[self.tableView reloadData]
后,tableView会检查表中有多少行。此时,numberOfRowsInSection
将返回[[ToDoItemSvc retrieveAllToDoItems] count]
。现在这应该比删除行之前的1
小。
简短的回答是,您需要先从dataSource中删除一个项目,该项目似乎是[ToDoItemSvc retrieveAllToDoItems]
,然后删除一行。
对此的补充是,当您添加一行时,您还需要向dataSource添加一个项目。
在您致电reloadData
之前,需要进行这些更改。
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
// Actually remove the data from the source
[ToDoItemSvc deleteToDoItem:[ToDoItemSvc retrieveAllToDoItems][indexPath.row]]
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView reloadData];
}
ELI5:老师有五个学生:Alice,Bob,Charlie,Diane和Eric。鲍勃的妈妈在午餐前从学校提早接他。午餐后,老师会出席和恐慌,因为他只有四个孩子,因为名单上应该有五个孩子。鲍勃在哪里?!
如果鲍勃的妈妈在带他离开学校时从名单上删除了他的名字,那么老师就不会惊慌失措。
答案 1 :(得分:2)
我在上面的帮助下想出了一些想法。
首先,我完成了实际的deleteToDoItem代码
- (ToDoItem *) deleteToDoItem: (ToDoItem *) todoitem {
[ToDoItems removeObject:todoitem];
return todoitem;
}
然后是上面的代码
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
ToDoItem *toDoItem = [[ToDoItemSvc retrieveAllToDoItems] objectAtIndex:indexPath.row];
[ToDoItemSvc deleteToDoItem:toDoItem];
[self.tableView reloadData];
NSLog(@"Removing data");
}
这会运行并允许我删除我想要的项目!!