Связи CoreData равны нулю после mergeChangesFromContextDidSaveNotification

Поистине странное поведение с Core Data на iOS.

У меня есть NSManagedObjectContext для моего основного потока, который используется для чтения данных из постоянного хранилища SQLLite и отображения их пользователю. У меня также есть фоновые процессы, которыми управляет NSOperationQueue. Эти фоновые процессы создают NSMangedObjectContext, получают данные с удаленных серверов и сохраняют эти данные в локальном хранилище Core Data.

Я зарегистрировался на NSManagedObjectContextDidSaveNotification, и когда я получаю эти уведомления, я вызываю mergeChangesFromContextDidSaveNotification в NSManagedObjectContext основного потока (передавая объект уведомления в качестве аргумента).

Все это очень стандартно, и весь документ Core Data предлагает вам иметь дело с многопоточностью.

До недавнего времени я всегда вставлял новые объекты в хранилище данных и не изменял объекты в хранилище данных. Это сработало. После того, как фоновый поток записывает новые данные, происходит слияние, я отправляю уведомление в UIController и перерисовываю свой дисплей. Дисплей рисует правильно.

Недавно я внес изменение, и фоновый поток одновременно вставляет и изменяет объекты. Но в остальном картина остается прежней. Теперь после слияния данные в NSManagedObjectContext моего основного потока повреждены. Если я попытаюсь запросить объекты, я ничего не получу. Если я попытаюсь исследовать объекты, на которые у меня уже есть ссылка, все их отношения равны нулю (не ошибкам, а нулю). Я проверил базу данных SQLLite, и там все данные.

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

Хорошо, немного странностей. Если мой фоновый поток обновляет только атрибуты (примитивы), я не получаю такого странного поведения. Однако, если я обновляю сами отношения, я получаю эти пустые результаты запроса выборки и нулевые отношения.

Что мне не хватает?


person vm2000    schedule 24.02.2012    source источник
comment
Я только начал разрабатывать похожий дизайн и увидел кое-что из того же. Можете ли вы подтвердить, что вы случайно не вставили какие-либо вызовы пользовательского интерфейса в фоновый поток? Я уверен, вы знаете, что это может привести к плохому поведению и в некоторой степени непредсказуемо. Если это не так, покажите свой код для обновлений отношений.   -  person Jim    schedule 24.02.2012


Ответы (1)


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

person vm2000    schedule 24.02.2012
comment
так что же все-таки исправить? - person Danut Pralea; 03.08.2012