Pergunta

Eu estou usando um NSFetchedResultsController para gerenciar exibindo objetos gerenciados obtida numa vista de tabela que tem uma seção. A tabela começa vazio e o usuário pode adicionar novas entidades a ele usando a interface do usuário. Tal como está, o programa sempre funciona quando adicionando a primeira entidade, e sempre falha quando a adição de um segundo. Por vezes, há nenhum erro apresentado no momento do acidente e outras vezes há erros de diferentes tipos (alguns incluídos abaixo). Através de declarações de log e rastreamento Eu vejo que o programa trava logo após controllerWillChangeContent do delegado da NSFetchResultsController (que chama [self.tableView beginUpdates];) saídas de método, mas antes de qualquer outro método no meu código é chamado. Aqui estão algumas das peças relavant do meu código. Configurando o 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]);
}

Adicionando nova entidade:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Beer" inManagedObjectContext:self.managedObjectContext];
Beer *beer = [[Beer alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
beer.name = beerName;
beer.brewery = self.brewery;

Eu tenho visto as advertências nos docs sobre problemas que exibem tabelas com uma seção, e eu usei solução da Apple para que sem sucesso. Esses métodos não estão sendo chamados antes do acidente de qualquer maneira.

Alguns dos erros que eu recebi:

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)

Como você pode ver, os erros (quando foi apresentado) não são consistentes, mesmo quando nenhuma alteração ao código foi feita.

Alguém pode pensar no que eu estou fazendo errado?

Foi útil?

Solução

Seus erros inconsistentes apontam para um possível problema over-lançamento. Especialmente desde que mudar seus delegados apenas para recarregar os dados torna a questão ir embora. Pessoalmente eu gostaria de investir o tempo para resolver o problema em vez de codificação em torno dele, como você definitivamente tendo um problema de código lá que provavelmente irá aparecer mais tarde em outro lugar.

Eu faria o seguinte:

  1. Ligue NSZombie
  2. Adicionar um ponto de interrupção para objc_exception_throw
  3. Executar no depurador

Quando a exceção ocorre, olhar para o endereço de memória e ver o que está sendo acessado e onde. Isto irá isolar o problema e dizer-lhe o que está acontecendo. Também seria útil, se isso não revelar o problema, para publicar seus métodos NSFetchedResultsController delegado para que eu possa ver se há alguma coisa estranha em si.

Melhor para atualizar a pergunta original com as informações adicionais.

Outras dicas

O código para criar novas entidades é tudo estranho. Que tal usar este em vez disso:

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

Além disso, você não está chamando NSManagedObjectContext#save:. Mas talvez você está fazendo isso em uma parte do seu código que se mostram agora?

Enquanto eu não resolver este problema particular, eu levei uma abordagem um pouco diferente de escrever a classe que deu o a funcionalidade que eu quero e não causa o problema a surgir. Eu ainda estou usando NSFetchedResultsController, mas em vez de implementar todos os quatro métodos de delegado, só estou implementando controllerDidChangeContent :, que apenas chama [tableView reloadData].

Esta é a implementação que está incluído na classe RootViewController se você criar um novo aplicativo de navegação baseado em XCode que usa Core Data para armazenamento. Você provavelmente perder algum controle sobre a mesa-editar animações, mas é muito simples e funciona bem para os meus propósitos.

Eu tinha um bug semelhante recentemente - seu problema é com mais de liberar, em particular:

[sortDescriptors release];

Você obtém os sortDescriptors objeto de

[NSArray arrayWithObjects:sortDescriptor, nil];

que não tem "alloc", "cópia" ou "novo", para que ele retorna um objeto autoreleased. Porque você liberá-lo mais cedo, você tem dois lugares onde você pode Crash - quando o NSFetchRequest usa-lo, e quando ele é liberado na piscina. Consulte guia de gerenciamento de memória da Apple para obter mais detalhes .

Este é um velho, mas para o benefício de outras pessoas com o mesmo problema, eu gastei horas tentando entender o que estava acontecendo e ter finalmente encontrado um problema com meu descritor de tipo que estava causando essas falhas aleatórias.

As mensagens de erro variaram mas foram principalmente relacionados a um compareObject:. Selector toObject conforme abaixo

- [_ NSCFSet compareObject: toObject:]: selector não reconhecido enviada à instância - [ _NSCFString compareObject: toObject:] selector não reconhecido enviada à instância

A minha sugestão é tentar eliminar todos os descritores de classificação e predicados de seu código e, em seguida, adicioná-los um por um para descobrir onde está o problema.

Boa sorte! Rog

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top