![](/img/trans.png)
[英]App crashing with error: -[NSNull length]: unrecognized selector sent to instance
[英]Core Data app crashing with “controllerWillChangeContent : unrecognized selector sent to instance”
我有一個具有2個視圖的核心數據應用程序。 第一個視圖列出“房間”,第二個視圖列出房間中的“場景”。 “房間”頁面上有一個編輯NavItem按鈕,按下該按鈕將啟用添加NavItem按鈕。 您可以從此處刪除和添加房間。 添加的房間僅在表中以默認的“新房間”名稱顯示。 第二個視圖是所選房間中的場景列表。 同樣的操作,您可以刪除和添加場景,添加的場景僅在表中顯示為“新場景”。 真的沒什么特別的。
我在兩個視圖控制器中都使用了FetchedResultsController
,其中的Scenes具有一個NSPredicate
,僅返回所選房間中的場景。 我還使用controllerWillChangeContent
, controllerDidChangeContent
等代理方法來更新表視圖。
起初,這一切都很好,但是通常在房間和場景中瀏覽然后嘗試刪除場景后,它將崩潰。 如果玩了足夠長的時間,它將不可避免地崩潰。 它僅在刪除場景時發生。 如果按下編輯按鈕並刪除一個場景並且該場景有效,則該編輯會話中的以下所有刪除將始終有效。 它只會在第一次刪除編輯會話時崩潰。
我得到的錯誤是一個奇怪的錯誤:
由於未捕獲的異常“ NSInvalidArgumentException”而終止應用程序,原因:“-[__ NSCFType controllerWillChangeContent:]:無法識別的選擇器已發送到實例0x5e02d70”
該錯誤的第一部分有時會更改。 有時是__NSCFType
,有時是CALayer
。 僅在刪除場景時才會發生此錯誤。 添加場景可以100%完成。
我已經閱讀了另一篇有關stackoverflow的文章,該文章表明這類錯誤可能來自內存管理問題。 我已經仔細檢查了代碼,並使用檢漏儀在Instruments上運行了該代碼。 沒有泄漏。
還有什么我可以檢查的嗎? 有任何想法嗎?
這是相關的代碼。
從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將錯誤視為垃圾,因此將其視為異常。 嘗試將其初始化為nil。 它解決了我的問題。 該問題僅在4.2iOS上可見。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.