Представление таблицы на основе NSFetchedResultsController всегда завершается ошибкой при ВТОРОЙ вставке объекта - PullRequest
5 голосов
/ 11 февраля 2010

Я использую NSFetchedResultsController для управления отображением извлеченных управляемых объектов в табличном представлении, которое имеет один раздел.Таблица начинается пустой, и пользователь может добавлять новые объекты в нее с помощью пользовательского интерфейса.В существующем состоянии программа всегда работает при добавлении первого объекта и всегда вылетает при добавлении второго объекта.Иногда при сбое не возникает ошибок, а в других случаях возникают ошибки разных типов (некоторые из них приведены ниже).Посредством операторов журнала и трассировки я вижу, что программа падает сразу после выхода из метода controllerWillChangeContent делегата NSFetchResultsController (который вызывает метод [self.tableView beginUpdates];), но до вызова любого другого метода в моем коде.Вот некоторые из релевантных частей моего кода.Конфигурирование 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]);
}

Добавление нового объекта:

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

Я видел предупреждения в документах о проблемах отображения таблиц с одним разделом, и я использовал обходной путь Apple для этогоно безрезультатно.Эти методы в любом случае не вызывают до сбоя.

Некоторые из полученных мной ошибок:

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)

Как видите, ошибки (когда они были представлены)не согласуются, даже если в код не было внесено никаких изменений.

Может кто-нибудь понять, что я делаю неправильно?

Ответы [ 5 ]

4 голосов
/ 09 марта 2010

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

Я бы сделал следующее:

  1. Включите NSZombie
  2. Добавить точку останова для objc_exception_throw
  3. Запустить в отладчике

Когда возникает исключение, посмотрите на адрес памяти и посмотрите, что и где осуществляется доступ. Это изолирует проблему и скажет вам, что происходит. Также было бы полезно, если это не раскрывает проблему, опубликовать ваши NSFetchedResultsController методы делегата, чтобы я мог видеть, есть ли в них что-то странное.

Лучше всего обновить оригинальный вопрос дополнительной информацией.

1 голос
/ 20 января 2011

Недавно у меня была похожая ошибка - ваша проблема с переизданием, в частности:

[sortDescriptors release];

Вы получаете объект sortDescriptors из

[NSArray arrayWithObjects:sortDescriptor, nil];

, который не имеет «alloc», «copy» или «new», поэтому он возвращает автоматически выпущенный объект. Поскольку вы выпускаете его раньше, у вас есть два места, где вы можете потерпеть крах - когда NSFetchRequest использует его и когда он освобождается пулом. Смотрите Apple руководство по управлению памятью для более подробной информации.

1 голос
/ 12 февраля 2010

Хотя я не решил эту конкретную проблему, я использовал немного другой подход к написанию класса, который дал желаемую функциональность и не вызывал проблемы. Я все еще использую NSFetchedResultsController, но вместо того, чтобы реализовывать все четыре метода делегата, я только реализую controllerDidChangeContent:, который просто вызывает [tableView reloadData].

Это реализация, включенная в класс RootViewController, если вы создаете новое приложение на основе навигации в XCode, которое использует Core Data для хранения. Вы, вероятно, теряете некоторый контроль над анимацией редактирования таблиц, но это на намного проще и отлично подходит для моих целей.

1 голос
/ 11 февраля 2010

Ваш код для создания новых сущностей странный. Как насчет использования этого вместо:

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

Кроме того, вы не звоните NSManagedObjectContext#save:. Но, возможно, вы делаете это в той части кода, которую вы сейчас показывали?

0 голосов
/ 17 октября 2010

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

Сообщения об ошибках различались, но в основном они были связаны с селектором compareObject: toObject, как показано ниже.

- [_ NSCFSet compareObject: toObject:]: нераспознанный селектор, отправленный экземпляру - [ _NSCFString compareObject: toObject:] нераспознанный селектор, отправленный экземпляру

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

Удачи!Рог

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...