5

我正在使用 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)

如您所见,即使没有对代码进行任何更改,错误(出现错误时)也不一致。

谁能弄清楚我做错了什么?

4

5 回答 5

4

您的不一致错误表明可能存在过度发布问题。特别是因为将您的代表更改为仅重新加载数据会使问题消失。就我个人而言,我会花时间解决问题,而不是围绕它进行编码,因为你肯定会在那里遇到代码问题,以后可能会在其他地方出现。

我会做以下事情:

  1. 打开 NSZombie
  2. objc_exception_throw
  3. 在调试器中运行

发生异常时,查看内存地址,查看正在访问的内容和位置。这将隔离问题并告诉您发生了什么。如果这不能揭示问题,那么发布您的委托方法也会很有帮助,NSFetchedResultsController这样我就可以查看它们是否有任何奇怪之处。

最好用附加信息更新原始问题。

于 2010-03-09T14:57:31.063 回答
1

您创建新实体的代码很奇怪。不如改用这个:

Beer* beer = [NSEntityDescription insertNewObjectForEntityForName: @"Beer" 
    inManagedObjectContext: self.managedObjectContext];
beer.name = @"Grolsch";

另外,你没有打电话NSManagedObjectContext#save:。但也许你正在你现在展示的部分代码中这样做?

于 2010-02-11T03:20:58.697 回答
1

虽然我没有解决这个特定问题,但我采用了一种稍微不同的方法来编写提供了我想要的功能并且不会导致问题出现的类。我仍在使用 NSFetchedResultsController,但没有实现所有四个委托方法,我只实现了 controllerDidChangeContent:,它只是调用 [tableView reloadData]。

如果您在 XCode 中创建一个使用 Core Data 进行存储的新的基于导航的应用程序,则这是包含在 RootViewController 类中的实现。您可能会失去对表格编辑动画的一些控制,但它简单并且适合我的目的。

于 2010-02-11T21:12:56.750 回答
1

我最近有一个类似的错误 - 你的问题是过度释放,特别是:

[sortDescriptors release];

您从中获得 sortDescriptors 对象

[NSArray arrayWithObjects:sortDescriptor, nil];

它没有“alloc”、“copy”或“new”,所以它返回一个自动释放的对象。因为你提前释放它,你会在两个地方崩溃——当 NSFetchRequest 使用它时,以及当它被池释放时。有关更多详细信息,请参阅苹果的内存管理指南

于 2011-01-20T14:34:22.870 回答
0

这是一个旧的,但为了其他有同样问题的人的利益,我花了几个小时试图了解发生了什么,最后发现我的排序描述符存在问题,导致这些随机崩溃。

错误消息各不相同,但主要与 compareObject:toObject 选择器有关,如下所示。

-[_ NSCFSet compareObject:toObject:]: 无法识别的选择器发送到实例 -[ _NSCFString compareObject:toObject:] 无法识别的选择器发送到实例

我的建议是尝试从您的代码中消除所有排序描述符和谓词,然后将它们一一添加以找出问题所在。

祝你好运!罗格

于 2010-10-17T09:09:39.217 回答