Установка отношения основных данных в NSOperation ... NSManagedObject был признан недействительным - PullRequest
0 голосов
/ 13 апреля 2011

У меня есть приложение Core Data, которое имеет структуру данных статей и комментариев (отношение один ко многим).

NSOperations управляет загрузкой и синтаксическим анализом JSON в другом потоке, тогда он использует mergeChangesFromContextDidSaveNotification для передачи изменений в основной поток, где он сохранен, а fetchedResultsController заботится об изменениях tableView.

Вызовы статей и комментариев выполняются в отдельных API-интерфейсах, вызываемых с сервера, и у каждого есть своя NSOperation для обработки импорта. (Они свободно основаны на классе Apple RSSImporter, но были изменены для JSON). Каждая операция имеет свой собственный контекст и использует storeCoordinator из fetchedResultsController.

commentParser.articleObjectID = [article objectID];
commentParser.persistentStoreCoordinator = [[self.fetchedResultsController managedObjectContext] persistentStoreCoordinator];

Я пытаюсь установить связь в NSOperation между статьей и комментариями, и я полагаю, что я следую передовым методам, передавая objectID статьи в операцию комментариев, а затем использую объект, выполнив следующее :

Article *article = (Article *)[self.insertionContext objectWithID:articleObjectID];
Comment *aComment = (Comment *)[NSEntityDescription insertNewObjectForEntityForName:@"Comment" inManagedObjectContext:self.insertionContext]; 
[aComment setCommentArticle:article];

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

* Завершение приложения из-за необработанного исключения 'NSObjectInaccessibleException', причина: «NSManagedObject с ID: 0xdb24f30 был признан недействительным. '

Любая помощь с этим будет оценена!

Ответы [ 3 ]

2 голосов
/ 13 апреля 2011

Дэмиен вывел вас на правильный путь. Вот как это сделать:

  1. Объект в вашей основной теме зарегистрирован для NSManagedObjectContextDidSaveNotification

  2. NSOperation загружает JSON и добавляет их в контекст управляемого объекта, инициализированный в операции, сохраняя контекст после добавления всех объектов.

  3. Когда появляется уведомление NSManagedObjectContextDidSaveNotification, убедитесь, что вы обрабатываете его в главном потоке. Если нет, перешлите сообщение на self в главном потоке. (см. пример кода Apple TopSongs для примера).

  4. При обработке NSManagedObjectContextDidSaveNotification в главном потоке вызовите [context mergeChangesFromContextDidSaveNotification:notification].

  5. Ваш NSFetchedResultsController будет отправлять соответствующие протокольные сообщения своему делегату, чтобы вы могли обновить свой интерфейс.

  6. Если вам необходимо уведомить объекты в вашем приложении любым другим способом, вы можете опубликовать уведомление для конкретного приложения, которое ваши объекты могут наблюдать и делать все, что им нужно.

Вы должны NOT передать идентификаторы объектов обратно из NSOperation в основной поток и снова вставить их в контекст. Вы уже сделали это в NSOperation. Если вам нужно знать новые идентификаторы объектов в вашем основном потоке, это нормально для их передачи и использования, но объекты уже были вставлены и сохранены в вашем контексте.

2 голосов
/ 13 апреля 2011

Вы должны сохранить новые сущности базовых данных (или изменения существующих) в потоке, который их создает (в постоянное хранилище), а затем передать идентификаторы объекта в основной поток, где NSManagedContext в этом потоке будет использовать objectID для извлечения объектов из постоянного хранилища.

Посмотрите на: http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html

Поэтому убедитесь, что вы сохраняете новые объекты (или измененные объекты) в NSManagedObjectContext, который вы создали в фоновом потоке, и тогда все должно работать нормально.

0 голосов
/ 14 апреля 2011

Одна вещь для проверки:

ManagedObjectIDs - это просто временные идентификаторы, пока объект не будет сохранен в хранилище.Таким образом, если вы берете идентификатор вновь созданного объекта и передаете его другому потоку / операции до того, как объект будет сохранен, тогда у него будет только временный идентификатор, который изменится, когда объект будет фактически сохранен каким-либо потоком / операцией.,

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

...