基于 NSFetchedResultsController 的表视图在第二次插入实体时总是失败
-
19-09-2019 - |
题
我正在使用 NSFetchedResultsController 来管理在具有一个部分的表视图中显示获取的托管对象。该表一开始是空的,用户可以使用 UI 向其中添加新实体。就目前情况而言,程序在添加第一个实体时始终有效,而在添加第二个实体时始终崩溃。有时崩溃时不会出现错误,有时会出现不同类型的错误(下面包括一些错误)。通过日志语句和跟踪,我发现程序在 NSFetchResultsController 的委托的controllerWillChangeContent(调用 [self.tableView beginUpdates];)方法退出之后崩溃,但在调用我的代码中的任何其他方法之前。这是我的代码的一些相关部分。配置 NSFetchedResultsController:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Beer"
inManagedObjectContext:self.managedObjectContext]];
// Configure request's entity and predicate
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
NSString *expression = [NSString stringWithFormat:@"brewery.name LIKE \"%@\"", self.brewery.name];
NSPredicate *predicate = [NSPredicate predicateWithFormat:expression];
[fetchRequest setPredicate:predicate];
self.resultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
self.resultsController.delegate = self;
[fetchRequest release];
NSError *error = nil;
BOOL success = [resultsController performFetch:&error];
if (!success) {
NSLog(@"Error fetching request %@", [error localizedDescription]);
}
添加新实体:
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Beer" inManagedObjectContext:self.managedObjectContext];
Beer *beer = [[Beer alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
beer.name = beerName;
beer.brewery = self.brewery;
我在文档中看到了有关显示带有一个部分的表格的问题的警告,并且我使用了 Apple 的解决方法,但没有效果。无论如何,这些方法在崩溃之前不会被调用。
我收到的一些错误:
Serious application error. Exception was caught during Core Data change processing: *** -[NSCFString compareObject:toObject:]: unrecognized selector sent to instance 0x4e808c0 with userInfo (null)
Serious application error. Exception was caught during Core Data change processing: *** -[CALayer compareObject:toObject:]: unrecognized selector sent to instance 0x4e53b80 with userInfo (null)
Serious application error. Exception was caught during Core Data change processing: *** -[UITextTapRecognizer controllerWillChangeContent:]: unrecognized selector sent to instance 0x4ca5d70 with userInfo (null)
Serious application error. Exception was caught during Core Data change processing: *** -[CALayer controllerWillChangeContent:]: unrecognized selector sent to instance 0x4e271a0 with userInfo (null)
Serious application error. Exception was caught during Core Data change processing: *** -[NSCFNumber countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x4c96ee0 with userInfo (null)
正如您所看到的,即使没有对代码进行任何更改,错误(当出现错误时)也不一致。
谁能弄清楚我做错了什么吗?
解决方案
您不一致的错误表明可能存在过度发布问题。特别是因为将您的委托更改为仅重新加载数据可以使问题消失。就我个人而言,我会投入时间来解决问题,而不是围绕它进行编码,因为您肯定会遇到代码问题,并且稍后可能会在其他地方出现。
我会做以下事情:
- 打开 NSZombie
- 添加断点
objc_exception_throw
- 在调试器中运行
当异常发生时,查看内存地址,看看正在访问什么以及在哪里。这将隔离问题并告诉您发生了什么。如果这没有揭示问题,发布您的信息也会很有帮助 NSFetchedResultsController
委托方法,这样我就可以看看它们是否有什么奇怪的地方。
最好用附加信息更新原始问题。
其他提示
您的代码来创建新的实体是所有怪异。什么有关使用该代替:
Beer* beer = [NSEntityDescription insertNewObjectForEntityForName: @"Beer"
inManagedObjectContext: self.managedObjectContext];
beer.name = @"Grolsch";
另外,你是不是叫NSManagedObjectContext#save:
。但是,也许你正在做的,在你的代码的一部分,你没有现在证明?
虽然我没有解决这方面的问题,我参加了一个稍微不同的方法,以书面形式给了我想要的功能,并没有导致出现问题的类。我仍在使用NSFetchedResultsController,但不是执行所有四个委托方法,我只是执行controllerDidChangeContent :,它只是调用[的tableView reloadData]。
这是,如果你在Xcode中创建一个使用核心数据存储新的导航为基础的应用程序,包括在RootViewController的类的实现。你可能失去对表编辑动画一定的控制,但它的多的简单,我的目的,工作正常。
我最近也有类似的错误 - 你的问题是一个拥有释放,特别是:
[sortDescriptors release];
您获得sortDescriptors从
对象[NSArray arrayWithObjects:sortDescriptor, nil];
不具有“黄金”,“复制”或“新”,所以它返回一个自动释放物体。因为你提前释放它,你会得到两个地方可能会崩溃 - 当NSFetchRequest使用它,当它被释放池。详情参见苹果的内存管理指南 。
这是一个古老的,但对于有同样的问题其他人的利益,我已经花了几个小时试图了解发生了什么事情,并最终发现这是造成这些随机崩溃我的排序描述符的问题。
改变的错误消息,但大多涉及一个compareObject:toObject选择器按以下
。- [_ NSCFSet compareObject:toObject:]:无法识别的选择发送到实例 - [ _NSCFString compareObject:toObject:]无法识别的选择发送到实例
我的建议是,试图消除你的代码的所有类型的描述符和谓词,然后逐个增加他们一个发现问题的所在。
祝你好运! ROG