NSFetchedResultsController retornando objetos com indexPaths nulos
Os detalhes estão nos comentários.
O código a seguir:
// Perform the fetch...
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
// Confirm that objects were fetched by counting them...
NSLog(@"Number of Objects = %i",
[[fetchedResultsController fetchedObjects] count]);
// Confirm that sections exist by counting them...
NSLog(@"Numbers of Sections = %i",
[[fetchedResultsController sections] count]);
for (id section in [fetchedResultsController sections]) {
// Count number of objects in each section
// _The fact that this outputs 0 is the first sign of trouble_
NSLog(@"Number of Objects in Section = %i", [section numberOfObjects]);
}
for (Reminder *reminder in [fetchedResultsController fetchedObjects]) {
// Confirm that the objects fetched are in fact real objects
// by accessing their "textContent" property...
NSLog(@"textContent=%@", reminder.textContent);
// Show that the fetched objects are being returned
// with a (null) indexPath...
// _The second sign of trouble..._
NSLog(@"IndexPath=%@",
[fetchedResultsController indexPathForObject:reminder]);
}
NSUInteger indexArr[] = {0,0};
NSIndexPath *indexPath = [NSIndexPath indexPathWithIndexes:indexArr
length:2];
// _Application crashes on this line because the fetched
// objects do not have indexPaths_
Reminder *testReminder = (Reminder *)[fetchedResultsController
objectAtIndexPath:indexPath];
NSLog(@"textContent = %@", testReminder.textContent);
Resultados na seguinte saída:
2010-07-17 00:48:41.865 Reminders[27335:207] Number of Objects = 3
2010-07-17 00:48:41.867 Reminders[27335:207] Numbers of Sections = 1
2010-07-17 00:48:41.868 Reminders[27335:207] Number of Objects in Section = 0
2010-07-17 00:48:41.870 Reminders[27335:207] textContent=Imported Object 3
2010-07-17 00:48:41.871 Reminders[27335:207] IndexPath=(null)
2010-07-17 00:48:41.873 Reminders[27335:207] textContent=Imported Object 2
2010-07-17 00:48:41.873 Reminders[27335:207] IndexPath=(null)
2010-07-17 00:48:41.874 Reminders[27335:207] textContent=Imported Object 1
2010-07-17 00:48:41.875 Reminders[27335:207] IndexPath=(null)
2010-07-17 00:48:41.887 Reminders[27335:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'
Qualquer idéia seria muito apreciada. Para sua informação, o código acima funciona perfeitamente em um aplicativo separado se eu usar um modelo diferente como ponto de partida. I.e. se eu usar o modelo "Aplicativo baseado em janela", o código falhará. Se eu usar "Aplicativo baseado em navegação", o código funcionará conforme o esperado.
Atualizar: O TechZen queria saber se o problema é causado por minha entidade Lembrete. Eu pensei que era uma boa ideia investigar, então fiz o seguinte:
Crie dois aplicativos de modelo padrão: um "aplicativo baseado em janela" e um "aplicativo baseado em navegação" (ambos com o Core Data ativado)
Copiado sobre o código mínimo necessário do Nav-based para o Window para executar o teste acima (praticamente apenas o arquivo "xcdatamodel", o fetchedresultscontroller e uma maneira de adicionar objetos de teste).
O código acima ainda falha no novo aplicativo baseado em janela "Reminder-entity free". (Neste novo aplicativo de teste, na verdade, existe um código zero que eu mesmo me criei (fora do código de teste), é tudo apenas código de modelo recortado e colado.)
Então agora eu estou procurandode qualquer forma para executar o código acima depois de criar um "aplicativo baseado em janela". Aqui está o código para executar o teste usando a entidade padrão da nav, caso alguém esteja interessado em experimentá-lo:
ATUALIZAR Observe que, como o TechZen observou abaixo, esse código falhará, independentemente de ser executado com um banco de dados vazio; portanto, se iniciar a partir de um aplicativo baseado em janela, adicione primeiro alguns objetos ao banco de dados e adicione o código de teste.
// Confirm that objects were fetched
NSLog(@"Number of Objects = %i",
[[fetchedResultsController fetchedObjects] count]);
// Confirm that sections exist
NSLog(@"Numbers of Sections = %i",
[[fetchedResultsController sections] count]);
for (id section in [fetchedResultsController sections]) {
// Count number of objects in sections
// _The fact that this outputs 0 is the first sign of trouble_
NSLog(@"Number of Objects in Section = %i", [section numberOfObjects]);
}
for (NSManagedObject *managedObject in [fetchedResultsController fetchedObjects]) {
// Confirm that the objects fetched are in fact real objects,
// by accessing their "timeStamp" property
NSLog(@"TimeStamp=%@", [[managedObject valueForKey:@"timeStamp"] description]);
// Show that the fetched objects are being returned
// with a (null) indexPath
// _The second sign of trouble..._
NSLog(@"IndexPath=%@",
[fetchedResultsController indexPathForObject:managedObject]);
}
NSUInteger indexArr[] = {0,0};
NSIndexPath *indexPath = [NSIndexPath indexPathWithIndexes:indexArr
length:2];
// _Application crashes on this line, because the fetched
// objects do not have indexPaths_
NSManagedObject *managedObject = [fetchedResultsController
objectAtIndexPath:indexPath];
NSLog(@"textContent = %@", [[managedObject valueForKey:@"timeStamp"] description]);
ATUALIZAR aqui está a saída ao usar o novo código recortado e colado
2010-07-18 15:33:41.264 Reminders[30898:207] Number of Objects = 3
2010-07-18 15:33:41.266 Reminders[30898:207] Numbers of Sections = 1
2010-07-18 15:33:41.267 Reminders[30898:207] Number of Objects in Section = 0
2010-07-18 15:33:41.270 Reminders[30898:207] TimeStamp=2010-07-18 13:59:00 -0400
2010-07-18 15:33:41.271 Reminders[30898:207] IndexPath=(null)
2010-07-18 15:33:41.272 Reminders[30898:207] TimeStamp=2010-07-18 13:59:00 -0400
2010-07-18 15:33:41.273 Reminders[30898:207] IndexPath=(null)
2010-07-18 15:33:41.274 Reminders[30898:207] TimeStamp=2010-07-18 13:58:59 -0400
2010-07-18 15:33:41.275 Reminders[30898:207] IndexPath=(null)
2010-07-18 15:33:41.276 Reminders[30898:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'
ATUALIZAR Portanto, reduzi esse problema a ser um problema relacionado à versão do SDK, agora tenho um projeto que, se eu compilar com o Simulator 3.2, ele travar, e com o Simulator 3.1.3, ele funcionará bem. MAS, se eu adicionar um UITableViewController, criar com o Simulator 3.2, ele funcionará bem novamente. Então eu criei umnovo stackoverflow poste para fazer a pergunta: Se você estiver usando NSFetchedResultsController sem um UITableViewController, como você interage com os objetos? (como os IndexPaths não são confiáveis).
ATUALIZAR Este problema foi (provisoriamente) resolvido usando -[NSFetchedResultsController fetchedObjects] objectAtIndex:]
para acessar os objetos.