Ios 删除对象时,null INDExpath
我无法理解这一点,但当我从Ios 删除对象时,null INDExpath,ios,core-data,nsfetchedresultscontroller,Ios,Core Data,Nsfetchedresultscontroller,我无法理解这一点,但当我从NSFetchedResultsController中删除对象时,似乎有一个空的indexPath 删除对象时,我会执行以下操作: - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle =
NSFetchedResultsController
中删除对象时,似乎有一个空的indexPath
删除对象时,我会执行以下操作:
- (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都是零。我可以记录我的对象,我确实看到了实体。它在[self.savedLowTestableView deleteRowsAtIndexPaths:@[indexPath]with RowAnimation: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接收路线实体(如果正在编辑路线),或者在创建新路线时插入一个新实体。因此,在viewController中,如果我正在编辑一个路由,因为我试图使用两个MOC,一个temp和一个main作为其父级,这样当用户决定取消并不创建新路由时,我可以轻松地扔掉一些东西,我需要将该路由转移到另一个上下文中,以使其他代码正常工作。所以“转移”看起来像:
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;
有了这段代码,我现在可以将位置添加到现有路线中,因为这些位置在相同的上下文中,但从主主主运行中心删除现有路线时会出现某种混乱。不知道为什么以及最好的解决方案是什么
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;
必须获取与路由关联的上下文。也有同样的问题,并通过确保NSFetchedResultsController始终使用相同的NSManagedContext来解决。例如,如果您使用fetch控制器从数据库中提取对象,并且以后要删除该对象,请确保fetch控制器使用与提取期间使用的托管上下文相同的托管上下文
NSFetchedResultsController针对使用UITableView进行了优化,UITableView是用户界面组件,用户界面应始终由主线程处理,因此无需在每次进入fetch时创建新的NSManagedContext。。。因此,实现此代码应该可以解决此问题:
@综合fetchedResultsController=\uu fetchedResultsController;
@综合managedObjectContext=u managedObjectContext
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil)
{
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = ap.persistentStoreCoordinator;
if (coordinator != nil)
{
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}
ap是指向AppDelegate的指针:
ap = [[UIApplication sharedApplication] delegate];
这段代码的作用是创建一个MOC实例,然后重用它。警告:这不是线程安全的,也不一定是线程安全的(因为您应该只在主线程中使用它),所以如果您误用它,它将无法工作
使用以下命令:
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil)
{
return __fetchedResultsController;
}
//create __fetchedResultsController
// do some fetching
return __fetchedResultsController;
}
因此,当您要填充表时:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [__fetchedResultsController.fetchedObjects count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSManagedObject *managedObject = [__fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [managedObject valueForKey:@"smth."];
return cell;
}
如果您的数据集仅发生更改:
__fetchedResultsController = nil;
[tableView reloadData]
包括nsfetchedResultsController和delegat方法在内的所有方法都可以正常工作,没有nil索引路径等等
希望我帮助了某人…既然你已经找到了答案,为什么不把你的答案作为答案发布,而不是放在问题中?以后别人会更容易找到的。