Pergunta

Eu tenho um nsfetchedResultScontroller como minha fonte de dados e implementei o NSFetchedResultScontrollerDelegate no meu UitableViewController personalizado. Estou usando o SectionNameKeypath para dividir meu conjunto de resultados em várias seções.

Em um dos meus métodos, estou adicionando alguns objetos ao contexto, todos em uma nova seção. No momento em que salvo os objetos, os métodos delegados são chamados corretamente. A ordem dos eventos:

// -controllerWillChangeContent: fires
[self.tableView beginUpdates]; // I do this

// -controller:didChangeSection:atIndex:forChangeType: fires for section insert
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]];

// -controller:didChangeObject:atIndexPath:forChangeType:newIndexPath fires many times
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                withRowAnimation:UITavleViewRowAnimationFade]; // for each cell

// -controllerDidChangeContent: fires after all of the inserts
[self.tableView endUpdates];  // <--- Where things go terribly wrong!!!

Na última chamada, "EndUpDates", o aplicativo sempre trava com:

Serious application error.  Exception was caught during Core Data change processing:
[NSCFArray objectAtIndex:]: index (5) beyond bounds (1) with userInfo (null)

Parece que as atualizações da tabela não estão sincronizadas com os dados NSFetchedResultSController de alguma forma e as coisas explodem. Estou seguindo os documentos no NSFetchedResultScontrollerDelegate, mas isso não está funcionando. Qual é a maneira certa de fazer isso?

ATUALIZAR: Eu criei um projeto de teste que exibe esse bug. Você pode baixá -lo em: Nsboom.zip

Foi útil?

Solução

O rastreamento do aplicativo, observo que o DidChangeSection é chamado primeiro, que insere uma seção inteira - e depois o DidChangeObject é chamado repetidamente.

O problema é que, na DidChangeSection, você insere uma seção inteira e, logo após a atualização da exibição da tabela, você está adicionando objetos à mesma seção. Este é basicamente um caso de atualizações sobrepostas ... (não é permitido mesmo em um bloco de início/final de atualizações).

Se você comentar a inserção de objeto individual, tudo funciona:

 case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;

Se você comentar a seção inserir:, não funciona - mas tive menos sorte com o InserTrowsinsection funcionando o tempo todo, e pode muito bem ser porque ainda não há seção (o que tenho certeza de que você estava inserindo a seção para começar). Você pode ter que detectar qualquer um dos casos para fazer inserções com a granularidade certa.

Em geral, tive muito mais sorte recarregando e inserindo seções inteiras do que as linhas, a visualização da tabela parece muito complicada de mim em torno dos que trabalham. Você também pode tentar o UitableViewRowanimationNone que parece operar com sucesso com mais frequência.

Outras dicas

Estou tendo o mesmo problema. Acho que o DidChangeSection dispara duas vezes. Uma vez quando você cria o objeto para inserção e uma vez quando você realmente o salva. Para mim, não deve ligar para o didChangeSection até que o salvamento seja chamado. Ou, no mínimo, a WillChangeSection seria chamada na criação do objeto, e o didchesecção chamado quando for salvo.

Agora estou analisando o método NSMANAGEDOBJETCONTEXTDIDSAVENOTIFICATION OBSERVER. Isso não faz parte do NSFetchedResultScontrollerDelegate Protocol, mas você pode se registrar para recebê -lo. Talvez isso seja chamado apenas quando eu realmente ligar para salvar e não antes.

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