我无法弄清楚这一点,但是当我从NSFetchedResultsController
.
当我删除我的对象时,我这样做:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the object
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
[self saveContext];
}
}
设置NSFetchedResultsController
:
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setFetchBatchSize:20];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Route" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *nameSort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
NSArray *sortDescriptors = @[nameSort];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Routes"];
self.fetchedResultsController = aFetchedResultsController;
self.fetchedResultsController.delegate = self;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error with NSFetchedResultsController: %@", [error description]);
abort();
}
return _fetchedResultsController;
}
这是发生故障的地方:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
switch (type) {
// Data was inserted - insert the data into the table view
case NSFetchedResultsChangeInsert: {
[self.savedRoutesTableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
// Data was deleted - delete the data from the table view
case NSFetchedResultsChangeDelete: {
[self.savedRoutesTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
case NSFetchedResultsChangeUpdate: {
SavedRoutesTableViewCell *cell = (SavedRoutesTableViewCell *)[self.savedRoutesTableView cellForRowAtIndexPath:indexPath];
[cell configureCellWithRoute:[controller objectAtIndexPath:newIndexPath]];
break;
}
case NSFetchedResultsChangeMove: {
[self.savedRoutesTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.savedRoutesTableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
default:
break;
}
}
在 didChangeObject 方法中,我的 indexPath 和 newIndexPath 都是 nil。我可以 NSLog 我的对象,我确实看到了实体。它在[self.savedRoutesTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
方法中崩溃,但以下情况除外:
CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. *** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0] with userInfo (null)
当我保存这个对象时,我像这样保存它:
self.route.name = routeName;
NSManagedObjectContext *tempContext = [self.route managedObjectContext];
[tempContext performBlock:^{
NSError *error = nil;
if (![tempContext save:&error]) {
NSLog(@"an error occurred: %@", [error localizedDescription]);
}
[self.managedObjectContext performBlock:^{
NSError *error = nil;
if (![_managedObjectContext save:&error]) {
NSLog(@"error in main context: %@", [error localizedDescription]);
}
}];
}];
我不太确定在哪里调试它,因为NSFetchedResultsController
只是没有返回已删除对象的 indexPath。有什么想法吗?提前致谢。
编辑: 好吧,我找到了导致错误的罪魁祸首,但我不确定为什么会这样。基本上我有一个 ViewController,如果它正在编辑路由,它会从主 MOC 接收一个 Route 实体,或者如果你正在创建一个新路由,它会插入一个新实体。所以在那个 viewController 中,如果我正在编辑一条路线,因为我正在尝试为其父级使用两个 MOC,一个临时和一个主,所以如果用户决定取消而不创建新路线,我可以轻松扔掉东西,我需要将该路线转移到其他上下文以使其他代码工作。所以“转移”看起来像:
NSManagedObjectContext *moc = _route.managedObjectContext;
NSManagedObjectID *routeId = [_route objectID];
self.tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
self.tempContext.parentContext = moc;
NSManagedObject *localRoute = [self.tempContext objectWithID:routeId];
self.route = localRoute;
使用此代码,我现在可以在现有路线中添加位置,因为这些位置位于相同的上下文中,但不知何故,它会搞砸从主 MOC 中删除现有路线。不知道为什么以及最好的解决方案是什么。