NSFetchedResultsController, возвращающий объекты с нулевым indexPaths - PullRequest
3 голосов
/ 17 июля 2010

Подробности в комментариях.

Следующий код:

// 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);

Результатом будет следующий вывод:

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)'

Любые идеи будут с благодарностью.К вашему сведению, приведенный выше код отлично работает в отдельном приложении, если я использую другой шаблон в качестве отправной точки.Т.е., если я использую шаблон «Window-based application», код потерпит неудачу.Если я использую «Приложение на основе навигации», код работает должным образом.

Обновление: TechZen интересовался, не вызвана ли проблема моей сущностью Напоминание.Я подумал, что это хорошая идея для изучения, поэтому я сделал следующее:

  1. Создание двух шаблонных приложений по умолчанию: «Приложение на основе окна» и «Приложение на основе навигации»(оба с включенными Базовыми данными)

  2. Скопировано по минимальному коду, необходимому от Nav на основе Window, чтобы выполнить вышеупомянутый тест (в значительной степени просто файл "xcdatamodel",контроллер fetchedresults и способ добавления тестовых объектов).

Приведенный выше код все еще не работает в новом приложении на основе окна «Без напоминания».(В этом новом тестовом приложении фактически есть нулевой код, который я создал сам (за пределами тестового кода), это всего лишь код шаблона, вырезанный и вставленный вместе.)

Итак, я ищудля любого способа , чтобы запустить приведенный выше код после создания «оконного приложения».Вот код для выполнения теста с использованием сущности по умолчанию на основе nav, на случай, если кто-то захочет попробовать его:

UPDATE Обратите внимание, что, как TechZen отметил ниже, этот код будет падатьнезависимо от того, что выполняется с пустой базой данных, поэтому при запуске из оконного приложения сначала добавьте несколько объектов в базу данных, а затем добавьте тестовый код.

// 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]);

UPDATE Вот вывод при использовании нового вырезанного и вставленного кода

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)'

ОБНОВЛЕНИЕ Итак, я сузил эту проблему до проблемы, связанной с версией SDK, у меня теперь есть проектчто если я собираюсь с помощью Simulator 3.2, он падает, а сборка с помощью Simulator 3.1.3 работает нормально.НО, если я добавлю UITableViewController, затем соберусь с Simulator 3.2, тогда он снова будет работать нормально.Поэтому я создал новую запись stackoverflow , чтобы задать вопрос: если вы используете NSFetchedResultsController без UITableViewController, как вы взаимодействуете с объектами?(поскольку IndexPath ненадежны).

ОБНОВЛЕНИЕ Эта проблема (ориентировочно) решена с помощью - [NSFetchedResultsController fetchedObjects] objectAtIndex:] для доступа к объектам.

Ответы [ 6 ]

3 голосов
/ 01 марта 2012

Вы пытались использовать NSFetchedResultsController в режиме отслеживания только памяти? (Отслеживание только в памяти: делегат не ноль и имя кэша файла установлено в ноль)

3 голосов
/ 23 июля 2010

Это можно обойти, используя - [NSFetchedResultsController fetchedObjects] objectAtIndex:]

2 голосов
/ 25 ноября 2010

Полагаю, глупо было бы указывать, что NSLog (@ "% @", indexPath) всегда будет возвращать ноль?

Вам нужно сделать

NSLog(@"section %i",(int)indexPath.section);
NSLog(@"row %i",(int)indexPath.row);

Не так ли?

1 голос
/ 24 марта 2013

Посмотрите на порядок сортировки дескрипторов fetchedResultsController.Поле ключа раздела должно сначала отсортировать sortDescriptor.

Если fetchedResultsController имеет более одного sortDescriptor и первый дескриптор не является полем ключа раздела, чем indexPathForObject: метод не может разрешить indexPath.

0 голосов
/ 18 июля 2010

Я скопировал и вставил ваш код в шаблон навигации Core Data по умолчанию, изменил сущность на Напоминание со строковым атрибутом textContent, и он работал нормально. В этом коде или настройке контроллера выбранных результатов нет ничего плохого.

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


Edit:

Убедитесь, что вы запускаете этот тест только после добавления некоторых объектов в контекст. Он рухнет, если нет объектов. Я протестирую с помощью шаблона на основе окна.

0 голосов
/ 17 июля 2010

Как выглядит создание NSFetchedResultsController?

Обновление

К вашему сведению, вы можете обновить свой вопрос с помощью кода вместо использования PasteBin.

Используете ли вы несколько потоков в этом коде в любом месте для доступа к NSFetchedResultsController?

...