Приложение Core Data аварийно завершает работу с «ControllerWillChangeContent: нераспознанный селектор отправлен в экземпляр»

У меня есть приложение с основными данными с двумя представлениями. Первый вид перечисляет «Комнаты», второй - «Сцены» в комнатах. Страница Rooms имеет кнопку редактирования NavItem, которая при нажатии включает кнопку добавления NavItem. Вы можете удалять и добавлять номера отсюда. Добавленные комнаты просто отображаются с "Новой комнатой" по умолчанию имя в таблице. Второй вид - это список сцен в выбранной комнате. То же самое здесь, вы можете удалять и добавлять сцены, а добавленные сцены просто появляются в таблице с именем «Новая сцена». Ничего особенного на самом деле.

Я использую FetchedResultsController в обоих контроллерах представления, при этом один из сцен имеет NSPredicate , чтобы возвращать только сцены из выбранной комнаты. Я также использую методы делегирования controllerWillChangeContent , controllerDidChangeContent и т. Д. Сначала все работает нормально, но обычно после навигации по комнатам и сценам пытаясь удалить сцену, она потерпит крах. Он неизбежно потерпит крах, если вы поиграете с ним достаточно долго. Это происходит только при удалении сцены. Если вы нажмете кнопку редактирования и удалите сцену, и она сработает, то все последующие удаления в этом сеансе редактирования будут работать всегда. Это произойдет только при первом удалении сеанса редактирования.

Я получаю странную ошибку:

Завершение работы приложения из-за необработанного исключения 'NSInvalidArgumentException', причина: '- [__ NSCFType controllerWillChangeContent:]: нераспознанный селектор отправлен на экземпляр 0x5e02d70 '

Первая часть этой ошибки иногда изменяется. Иногда это __NSCFType , иногда это CALayer . Эта ошибка возникает только при удалении сцен. Добавление сцен - это нормально на 100%.

Я читал еще одну статью о потоке стека, в которой говорится, что такого рода ошибки могут возникать из-за проблем с управлением памятью. Я дважды проверил код, а также провел его через инструменты с помощью инструмента утечки. Утечек нет.

Есть ли что-нибудь еще, что я могу проверить? Есть идеи?

Вот соответствующий код ..

От 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;
} 
7
задан Dharmesh Dhorajiya 28 August 2015 в 10:58
поделиться

1 ответ

Эта ошибка, скорее всего, исходит от NSFetchedResultsController , у которого есть освобожденный делегат. У вас есть UIViewController , который вы выпустили и не выпустили связанный NSFetchedResultsController ?

28
ответ дан 6 December 2019 в 06:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: