我收到此错误:
CoreData:错误:严重的应用程序错误。抓住了一个例外 在调用期间来自NSFetchedResultsController的委托 -controllerDidChangeContent :.尝试删除第0部分中的第5行,该部分在使用userInfo(null)更新之前仅包含1行。如果我 编辑第一个或第二个而不是最后一切都在工作。
我有一个tableview和UISearchController,当我触摸tableview中的行时,它会发送给我另一个vc,我可以编辑我的日记。 一切都工作得很好,除非我搜索一些东西,如果结果是我的TableView的最后一个条目,当我尝试编辑并保存它时,给我上面写的错误。
@implementation PlumbListTableViewController
-(void)viewDidLoad {
[super viewDidLoad];
[self.fetchedResultsController performFetch:nil];
}
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
self.searchController =[[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
self.tableView.tableHeaderView = self.searchController.searchBar;
self.searchController.searchBar.delegate = self;
self.tabBarController.tabBar.hidden = NO;
[self showTotalSum];
[self.tableView reloadData];
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
[self.tableView reloadData];
}
- (void)searchForText:(NSString *)searchText
{
CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"AddEntry"];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];
if (self.searchController.searchBar.text.length == 0) {
NSError *error = nil;
self.filteredList = [coreDataStack.managedObjectContext executeFetchRequest:fetchRequest error:&error];
} else {
if (coreDataStack.managedObjectContext) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"titluPlumb contains[c] %@", searchText];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
self.filteredList = [coreDataStack.managedObjectContext executeFetchRequest:fetchRequest error:&error];
}
}
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchString = searchController.searchBar.text;
[self searchForText:searchString ];
[self.tableView reloadData];
}
-(void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope
{
[self updateSearchResultsForSearchController:self.searchController];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"edit"]) {
UITableViewCell *cell = sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
UINavigationController *navigationController = segue.destinationViewController;
PlumbAddViewController *entryViewController = (PlumbAddViewController *)navigationController.topViewController;
if (self.searchController.active) {
entryViewController.entry = [self.filteredList objectAtIndex:indexPath.row];
} else {
entryViewController.entry = [self.fetchedResultsController objectAtIndexPath:indexPath];
}
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
if (self.searchController.active)
{
return [self.filteredList count];
}
else
{
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
return [sectionInfo numberOfObjects];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
ConfigureCellPlumb *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
AddEntry *entry = nil;
if (self.searchController.active){
entry = [self.filteredList objectAtIndex:indexPath.row];
} else {
entry = [self.fetchedResultsController objectAtIndexPath:indexPath];
}
cell.titluView.text = entry.titluPlumb;
cell.descriereView.text = entry.bodyPlumb;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MM/dd/yyyy"];
NSDate *date = [NSDate dateWithTimeIntervalSince1970:entry.date];
cell.dataLabel.text = [dateFormatter stringFromDate:date];
if (entry.imageDataPlumb) {
cell.imagineView.image = [UIImage imageWithData:entry.imageDataPlumb];
} else {
cell.imagineView.image = [UIImage imageNamed:@"icn_noimage"];
}
return cell;
}
- (NSFetchRequest *)entryListFetchRequest {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"AddEntry"];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];
return fetchRequest;
}
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
NSFetchRequest *fetchRequest = [self entryListFetchRequest];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:coreDataStack.managedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
AddEntry *entry = [self.fetchedResultsController objectAtIndexPath:indexPath];
CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
[[coreDataStack managedObjectContext] deleteObject:entry];
[coreDataStack saveContext];
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
switch (type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeUpdate:
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeMove:
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch (type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeUpdate:
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
@end
更新:
- (NSFetchRequest *)entryListFetchRequest {
self.searchFetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"AddEntry"];
self.searchFetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];
return self.searchFetchRequest;
}
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
self.coreDataStack = [CoreDataStack defaultStack];
NSFetchRequest *fetchRequest = [self entryListFetchRequest];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.coreDataStack.managedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];
_fetchedResultsController.delegate = self;
if (self.searchController.searchBar.text.length != 0) {
NSString *searchText = self.searchController.searchBar.text;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"titluPlumb contains[c] %@", searchText];
[self.searchFetchRequest setPredicate:predicate];
NSError *error = nil;
self.filteredList = [self.coreDataStack.managedObjectContext executeFetchRequest:self.searchFetchRequest error:&error];
}
return _fetchedResultsController;
}
更新2
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
self.coreDataStack = [CoreDataStack defaultStack];
NSFetchRequest *fetchRequest = [self entryListFetchRequest];
if (self.searchController.searchBar.text.length !=0) {
NSString *searchText = self.searchController.searchBar.text;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"titluPlumb contains[c] %@", searchText];
fetchRequest.predicate = predicate;
}
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.coreDataStack.managedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
self.fetchedResultsController = nil; [self.tableView reloadData];
}
}
更新3
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
ConfigureCellPlumb *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
AddEntry *entry = nil;
entry = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.titluView.text = entry.titluPlumb;
cell.descriereView.text = entry.bodyPlumb;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MM/dd/yyyy"];
NSDate *date = [NSDate dateWithTimeIntervalSince1970:entry.date];
cell.dataLabel.text = [dateFormatter stringFromDate:date];
if (entry.imageDataPlumb) {
cell.imagineView.image = [UIImage imageWithData:entry.imageDataPlumb];
} else {
cell.imagineView.image = [UIImage imageNamed:@"icn_noimage"];
}
return cell;
}
更新4
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
self.coreDataStack = [CoreDataStack defaultStack];
self.searchFetchRequest = [self entryListFetchRequest];
if (self.searchController.searchBar.text.length !=0) {
NSString *searchText = self.searchController.searchBar.text;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"titluPlumb contains[c] %@", searchText];
self.searchFetchRequest.predicate = predicate;
[self.tableView reloadData];
}
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:self.searchFetchRequest managedObjectContext:self.coreDataStack.managedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];
_fetchedResultsController.delegate = self;
return [_fetchedResultsController fetchedObjects];
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
self.fetchedResultsController = nil;
[self.tableView reloadData];
NSLog(@"%@", self.searchFetchRequest.predicate);
}
答案 0 :(得分:1)
问题是你的桌面视图同时由2个源驱动(在这种情况下),因为你在搜索时没有完全关闭FRC。因此,您进行搜索并进行编辑,FRC会看到并尝试更新表格,但是 - 表格当前没有显示FRC行 - 所以有时它会失败。
使用FRC通过更改获取请求中的谓词来执行搜索,或者在您进行搜索时销毁FRC并在完成后重新创建它。
因此,将您的FRC方法更改为:
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
self.coreDataStack = [CoreDataStack defaultStack];
NSFetchRequest *fetchRequest = [self entryListFetchRequest];
if (self.searchController.searchBar.text.length != 0) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"titluPlumb contains[c] %@", searchText];
fetchRequest.predicate = predicate;
}
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.coreDataStack.managedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
每当您开始搜索/更改搜索文本/结束搜索时,请执行以下操作:
self.fetchedResultsController = nil;
[self.tableView reloadData];