Базовые данные - цикл прерывания сохранения родительского контекста
Допустим, у нас есть две сущности в модели базовых данных: отделы и сотрудники.
Департамент имеет отношение один-ко-многим к Сотрудникам.
У меня есть следующие ManagedObjectContexts:
- Root: подключен к координатору постоянного хранилища
- Main: контекст с родительским Root
Когда я хочу создать сотрудника, я делаю следующее:
- У меня есть отдел в основном контексте
- Я создаю Сотрудника в Основном контексте
- Я присваиваю Департамент имуществу департамента Сотрудника
- Я сохраняю Основной контекст
- Я сохраняю корневой контекст
Это создает цикл сохранения как в контексте Main, так и в контексте Root.
Если бы я сделал это без дочернего контекста (все в контексте Root), то я мог бы прервать цикл сохранения, вызвавrefreshObject:mergeChanges
на сотрудника. В моей ситуации с двумя контекстами я все еще мог бы использовать этот метод, чтобы разорвать цикл в контексте Main, но как мне разорвать цикл в контексте Root?
Примечание: это простой пример для описания моей проблемы. В инструментах я ясно вижу, как растет количество выделений. В моем приложении контексты, которые выходят за пределы одного уровня, вызывают еще большую проблему, потому что я получаю новое распределение сущностей с сохранением цикла для каждого контекста, который я сохраняю.
Обновление 15/04: NSPrivateQueueConcurrencyType vs NSMainQueueConcurrencyType
После сохранения обоих контекстов я могу выполнитьrefreshObject:mergeChanges
Основной контекст с объектом отдела. Это, как и ожидалось, приведет к повторной ошибке объекта «Отдел», нарушит цикл сохранения и освободит объекты «Отдел» и «Сотрудник» в этом контексте.
Следующим шагом является прерывание цикла сохранения, существующего в контексте Root (сохранение основного контекста распространяет сущности в контекст Root). Я могу сделать тот же трюк здесь и использоватьrefreshObject:mergeChanges
в контексте Root с объектом Department.
Странно то, что это работает нормально, когда мой корневой контекст создается с помощью NSMainQueueConcurrencyType (все выделения повторяются и освобождаются), но не работает, когда мой корневой контекст создается с помощью NSPrivateQueueConcurrencyType (все выделения повторяются, ноне dealloced).
Примечание: все операции для корневого контекста выполняются в вызове executeBlock (AndWait).
Обновление 15/04: часть 2
Когда я выполняю другое (бесполезное, потому что нет изменений) сохранение или откат в контексте Root с помощью NSPrivateQueueConcurrencyType, объекты, кажется, освобождаются. Я не понимаю, почему это не ведет себя так же, как NSMainQueueConcurrencyType.
Обновление 16/04: демонстрационный проект
Я создал демонстрационный проект:http://codegazer.com/code/CoreDataTest.zip
Обновление 21/04: как добраться
Спасибо Джоди Хейгингс за вашу помощь!
Я пытаюсь переместитьrefreshObject:mergeChanges
из моего ManagedObjectdidSave
методы.
Не могли бы вы объяснить мне разницу между:
[rootContext performBlock:^{
[rootContext save:nil];
for (NSManagedObject *mo in rootContext.registeredObjects)
[rootContext refreshObject:mo mergeChanges:NO];
}];
а также
[rootContext performBlock:^{
[rootContext save:nil];
[rootContext performBlock:^{
for (NSManagedObject *mo in rootContext.registeredObjects)
[rootContext refreshObject:mo mergeChanges:NO];
}];
}];
Верхний не освобождает объекты, нижний делает.