在 tableViewController 中使用重新加载的 CoreData
Posted
技术标签:
【中文标题】在 tableViewController 中使用重新加载的 CoreData【英文标题】:Work with reloaded CoreData in tableViewController 【发布时间】:2014-03-13 16:08:46 【问题描述】:我在将数据保存到 CoreData 并在表格视图控制器上显示时遇到问题。问题在此视频中:https://www.youtube.com/watch?v=6Di9zeAeBWs&feature=youtu.be
当我删除类时不会出现任何问题。该课程已正确删除。(我的视频的第 1 部分)。但是当我添加一个新类时,程序报错:
2014-03-13 16:31:02.771 IISForTeachers[30568:70b] CoreData:错误:严重的应用程序错误。在调用 -controllerDidChangeContent: 期间,从 NSFetchedResultsController 的委托中捕获了一个异常。无效更新:第 0 节中的行数无效。更新后现有节中包含的行数 (3) 必须等于更新前该节中包含的行数 (3),加上或减去数字从该部分插入或删除的行数(0 插入,1 删除)加上或减去移入或移出该部分的行数(0 移入,0 移出)。与 userInfo (null) 2014-03-13 16:31:02.774 IISForTeachers[30568:70b] _context SAVED 对持久存储的更改。
错误后将日期保存到持久存储。数据的保存工作正常,因为我在表格视图控制器中看到了新的类,当我停止并再次运行应用程序时,新数据就在那里。但是当我添加一个新类而不是删除一个类时,应用程序崩溃(视频的第 2 部分)。
当我再次运行应用程序时,新类在表格视图中,我删除它没有问题(第 3 部分)。
这是我删除单元格的函数代码:
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
if(debug == 1)
NSLog(@"Running %@ '%@'",self.class, NSStringFromSelector(_cmd));
CoreDataHelper *cdh = [(AppDelegate *) [[UIApplication sharedApplication] delegate] cdh];
if (editingStyle == UITableViewCellEditingStyleDelete)
SchoolClass *class = [self.frc objectAtIndexPath:indexPath];
[[class managedObjectContext] deleteObject:class];
[cdh saveContext];
[self.tableView reloadData];
FRC
在 ClassesTVC.m 中获取日期(表视图控制器,在哪里显示所有类)。
-(void)configureFetch
if(debug == 1)
NSLog(@"Running %@ '%@'",self.class, NSStringFromSelector(_cmd));
CoreDataHelper *cdh = [(AppDelegate *) [[UIApplication sharedApplication] delegate] cdh];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SchoolClass"];
request.sortDescriptors = [NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], nil];
[request setFetchBatchSize:50];
self.frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:cdh.context
sectionNameKeyPath:nil
cacheName:nil];
self.frc.delegate = self;
frc 在 CoreDataTVC.h(与表格视图控制器一起使用的通用类)中定义并定义为休闲:
@property (strong, nonatomic) NSFetchedResultsController *frc;
这里(CoreDataTVC)还有一个函数performFetch:
-(void)performFetch
if(debug == 1)
NSLog(@"Running %@ '%@'",self.class, NSStringFromSelector(_cmd));
if(self.frc)
[self.frc.managedObjectContext performBlock:^
NSError *error = nil;
if(![self.frc performFetch:&error])
NSLog(@"Failed to perform fetch: %@", error);
[self.tableView reloadData];
];
else
NSLog(@"Failed to fetch, the fetched results controller is nil.");
编辑-----------
我更改了我的代码,现在删除行的功能如下:
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
if(debug == 1)
NSLog(@"Running %@ '%@'",self.class, NSStringFromSelector(_cmd));
CoreDataHelper *cdh = [(AppDelegate *) [[UIApplication sharedApplication] delegate] cdh];
if (editingStyle == UITableViewCellEditingStyleDelete)
[tableView beginUpdates];
SchoolClass *class = [self.frc objectAtIndexPath:indexPath];
[[class managedObjectContext] deleteObject:class];
[tableView endUpdates];
[cdh saveContext];
[self.tableView reloadData];
现在应用程序运行良好,但仅当我插入一个输入(类名)时。当我插入班级名称并且班主任为空时,我可以删除有任何问题的单元格。但是,当我插入两个输入(班级名称、班级教师)时,应用程序再次显示错误。 这是对视频质量感到抱歉的应用程序行为:https://www.youtube.com/watch?v=PqSxqjuyZbU&feature=youtu.be
错误是一样的:
2014-03-14 12:15:08.309 IISForTeachers[35735:70b] CoreData:错误:严重的应用程序错误。在调用 -controllerDidChangeContent: 期间,从 NSFetchedResultsController 的委托中捕获了一个异常。无效更新:第 0 节中的行数无效。更新后现有节中包含的行数 (5) 必须等于更新前该节中包含的行数 (5),加上或减去数字从该部分插入或删除的行数(0 插入,1 删除)加上或减去移入或移出该部分的行数(0 移入,0 移出)。与 userInfo (null)
这是将 texfield 分配给对象类类型的代码。不知道哪里有问题。感谢您的帮助。
-(void)textFieldDidEndEditing:(UITextField *)textField
if (debug == 1)
NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));
CoreDataHelper *cdh = [(AppDelegate *)[[UIApplication sharedApplication]delegate]cdh];
SchoolClass *class = (SchoolClass*) [cdh.context existingObjectWithID:self.selectedClassID error:nil];
if(textField == self.classNameTextField)
if([self.classNameTextField.text isEqualToString:@""])
self.classNameTextField.text = @"Nova trida";
class.name = self.classNameTextField.text;
else if (textField == self.classTeacherTextField)
class.classTeacher = self.classTeacherTextField.text;
【问题讨论】:
你是如何实现你的 FRC 委托方法的? 删除commitForEditingStyle中的单元格而不是重新加载整个表格。[tableView deleteRows...等] 【参考方案1】:在删除单元格时适当地更新您的视图,该错误会准确地告诉您 UITableView 的期望。
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
if(debug == 1)
NSLog(@"Running %@ '%@'",self.class, NSStringFromSelector(_cmd));
CoreDataHelper *cdh = [(AppDelegate *) [[UIApplication sharedApplication] delegate] cdh];
if (editingStyle == UITableViewCellEditingStyleDelete)
[tableView beginUpdates];
SchoolClass *class = [self.frc objectAtIndexPath:indexPath];
[[class managedObjectContext] deleteObject:class];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[cdh saveContext];
[tableView endUpdates];
【讨论】:
我正在尝试使用您的代码,但现在在添加新类后无法“简单”删除或删除。错误在此屏幕截图上:dropbox.com/s/jibpbs99isheij0/… 错误是说 UITableView 在执行删除后仍然包含 4 行。因此 ' 必须包含在该部分中插入或删除的行数的正数或负数(1 已删除)。预计会有 3 行。 嗯,但我不知道怎么做。我用新代码更新我的问题。感谢您的帮助。 我认为您需要在结束更新之前将上下文保存在 CoreData 中,否则该对象仍然存在。 如果您使用的是 NSFetchResultsController 为什么不使用委托方法来处理内容更改?以上是关于在 tableViewController 中使用重新加载的 CoreData的主要内容,如果未能解决你的问题,请参考以下文章
tableViewController 中的 SideMenu
自定义 TableViewController 声音在 Swift 3 中播放和崩溃
在 Swift 3 中使用 didSelect 和 navigationController 在没有情节提要的情况下在 TableViewControllers 之间传递数据
在 TableViewController 的 pushViewController 方法中 navigationController = null (popover)
swift 4 中使用 performSegue 打开的关闭页面时,如何在视图控制器和 TableViewController 之间传递数据?