ManagedObjectContexts в разных потоках - разные ссылки на объекты - PullRequest
0 голосов
/ 23 марта 2012

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

Мои фоновые MOC создаются как дочерние элементы основного moc:

context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[context setParentContext:aConfiguration.context];
coordinator = aConfiguration.coordinator;
model = aConfiguration.model;
store = aConfiguration.store;
errorHandler = aConfiguration.errorHandler;

Так что большинство пока работает нормально, но есть существенная проблема. Я загружаю текстовые и графические данные. Поэтому в пользовательском интерфейсе я хочу сначала отобразить текст, а затем, для каждого загруженного изображения, исчезнуть в этом загруженном изображении. Обычно нет проблем, загрузчик завершает загрузку образа и вызывает своего делегата (Сервис) ala

downloder:(id<Downloader) aDownloader didFinishDownloadImageItem: (id) aObjectWithImage

, тогда как aObjectWithImage - это объект моей модели с новым загруженным изображением.

Делегат поместит объект в уведомление и опубликует это уведомление

NSDictionary *userInfo = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObject:aObjectWithImage]
                                                       forKeys:[NSArray arrayWithObject:EntityWithImageDownloadedNotificationInfoKeyEntity]];    
[[NSNotificationCenter defaultCenter] EntityWithImageDownloadedNotification object:self userInfo:userInfo];

И тут начинается проблема. Допустим, мой UIViewController будет наблюдать за этими уведомлениями. После получения он будет искать в своем массиве объектов, чтобы найти один в информационном словаре, чтобы изменить изображение.

Вы видите проблему? Он никогда не найдет этот объект! Из-за того факта, что первоначально этот объект был создан в фоновом потоке и, следовательно, в другом MOC, ссылки на объекты в массиве объекта UIViewController (основной MOC) всегда отличаются от того, который был опубликован в уведомлении (фоновый MOC).

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

Несколько предложений, как мне лучше справиться с этой проблемой?
Буду очень признателен за любые ваши идеи!

Ответы [ 2 ]

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

Под ссылкой я предполагаю, что вы имеете в виду objectID. Перед сохранением объекта в дочернем контексте вызовите [moc ObtainPermanentIDsForObjects: error:]. Затем сохраните файл, и вместо сохранения временных идентификаторов у него должны быть постоянные идентификаторы, которые будет извлекать ваш основной контекст.

Я где-то читал, что не нужно извлекать постоянный идентификатор, а вместо этого псевдоним временного идентификатора. Считайте, что это ошибка или особенность.

0 голосов
/ 23 марта 2012

Какой тип параллелизма вы используете?Я предполагаю NSPrivateQueueConcurrencyType для вашего фонового MOC, исходя из того, что вы говорите об использовании executeBlock: чтобы обернуть ваши запросы.Ваш основной поток MOC использует NSMainQueueConcurrencyType?

Я думаю, вы хотите сделать что-то вроде того, что описано в этот ответ .Внутри блока вашего фонового MOC, скажите вашему основному MOC выполнить блок и передать управляемый объект через его идентификатор объекта.

Вы можете спросить, как существует новый управляемый объект в MOC основного потока?Легко: вы делаете фоновый MOC дочерним по отношению к основному потоку MOC.Когда вы вызываете save для фонового MOC, он помещает свои новые объекты в родительский MOC, который является вашим основным.Сделайте это непосредственно перед передачей идентификатора объекта, и ваш объект будет там.

...