核心数据应用程序崩溃与“controllerWillChangeContent:无法识别的select器发送到实例”

我有一个有2个视图的核心数据应用程序。 第一个视图列出房间中的“房间”,第二个列表“场景”。 房间页面有一个编辑的NavItembutton,按下后可以添加一个NavItembutton。 您可以从这里删除和添加房间。 新增房间只是在表格中以默认的“新房”名称出现。 第二个视图是所选房间中的场景列表。 在这里同样的事情,你可以删除和添加场景,并添加场景只是出现在名称为“新场景”的表中。 没什么特别的

我在两个视图控制器中都使用了FetchedResultsController ,场景之一有NSPredicate只返回选定房间的场景。 我也使用controllerWillChangeContentcontrollerDidChangeContent等委托方法的表视图更新。

这一切都起初工作正常,但通常在导航房间和场景后,然后试图删除一个场景将崩溃。 如果你玩了足够长的时间,它将不可避免地崩溃。 只有在删除场景时才会发生。 如果按下编辑button并删除一个场景,它将起作用,那么在该编辑会话中的所有以下删除将始终工作。 它只会在第一次删除编辑会话时崩溃。

我得到的错误是一个奇怪的:

由于未捕获exception'NSInvalidArgumentException',原因:' – [__ NSCFType controllerWillChangeContent:]:发送到实例0x5e02d70的无法识别的select器'

这个错误的第一部分有时会改变。 有时它是__NSCFType ,有时候是CALayer 。 只有在删除场景时才会出现此错误。 添加场景很好100%。

我已经阅读了另一篇文章,提示这些错误可能来自内存pipe理问题。 我已经仔细检查了代码,并使用泄漏仪器通过仪器运行。 没有泄漏。

还有什么我可以检查? 有任何想法吗?

这是相关的代码

从ScenesTableViewController.m:

 // used to show/hide the add button - (void)setEditing:(BOOL)editing animated:(BOOL)animate { [super setEditing:editing animated:animate]; if(editing) { self.navigationItem.leftBarButtonItem = addButton; } else { self.navigationItem.leftBarButtonItem = nil; } } // called when the add button is pressed - (void)addAction { NSEntityDescription *myContentEntity = [NSEntityDescription entityForName:@"Scene" inManagedObjectContext:managedObjectContext]; Scene *contentToSave = [[Scene alloc] initWithEntity:myContentEntity insertIntoManagedObjectContext:managedObjectContext]; [contentToSave setValue:@"New Scene" forKey:@"Name"]; [parentRoom addRoomToScenesObject:contentToSave]; NSError *error; if (![managedObjectContext save:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); } [contentToSave release]; } // delegate method that's being sent unrecognised selectors - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { // The fetch controller is about to start sending change notifications, so prepare the table view for updates. [self.tableView beginUpdates]; } // cell display code - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = nil; cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (!cell) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; } [self configureCell:cell atIndexPath:indexPath]; return cell; } - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { NSManagedObject *mo = nil; NSString *temp = nil; mo = [fetchedResultsController objectAtIndexPath:indexPath]; temp = [mo valueForKey:@"Name"]; [[cell textLabel] setText:temp]; } // cell editing code - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the managed object at the given index path. [managedObjectContext deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]]; NSError *error; if (![managedObjectContext save:&error]) { // Update to handle the error appropriately. NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); // Fail } } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } } // NSFetchedResultsController code - (NSFetchedResultsController *)fetchedResultsController { if (fetchedResultsController != nil) { return fetchedResultsController; } /* Set up the fetched results controller. */ // Create the fetch request for the entity. NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; // Edit the entity name as appropriate. NSEntityDescription *entity = [NSEntityDescription entityForName:@"Scene" inManagedObjectContext:managedObjectContext]; NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Name" ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:nameDescriptor, nil]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SceneToRoom == %@)", parentRoom]; [fetchRequest setSortDescriptors:sortDescriptors]; [fetchRequest setPredicate:predicate]; [fetchRequest setEntity:entity]; // Edit the section name key path and cache name if appropriate. // nil for section name key path means "no sections". NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil]; aFetchedResultsController.delegate = self; self.fetchedResultsController = aFetchedResultsController; [aFetchedResultsController release]; [fetchRequest release]; [nameDescriptor release]; [sortDescriptors release]; return fetchedResultsController; } 

这个错误很可能来自一个NSFetchedResultsController ,它有一个释放的委托。 你有一个UIViewController你释放,并没有释放相关的NSFetchedResultsController

即使我面临同样的问题。 但是对于iOS 4.2来说,问题是NSError被初始化了,所以它被视为垃圾,并在更新/插入的时候被处理

 if (![managedObjectContext save:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); } 

所以在保存的时候,iOS将错误视为垃圾,所以这个exception。 尝试将其初始化为零。 它解决了我的问题。 这个问题只能在4.2iOS上看到。