Базовые данные - цикл прерывания сохранения родительского контекста
Позволять'скажем, у нас есть две сущности в базовой модели данных: отделы и сотрудники.
Департамент имеет отношение один-ко-многим к Сотрудникам.
У меня есть следующие ManagedObjectContexts:
- Root: подключен к координатору постоянного хранилища
- Main: контекст с родительским Root
Когда я хочу создать сотрудника, я делаю следующее:
- У меня есть отдел в основном контексте
- Я создаю Сотрудника в Основном контексте
- Я назначаю отдел сотрудникусобственность отдела
- Я сохраняю Основной контекст
- Я сохраняю корневой контекст
Это создает цикл сохранения как в контексте Main, так и в контексте Root.
Если бы я сделал это без дочернего контекста (все в контексте Root), то я мог бы прервать цикл сохранения, вызвавrefreshObject:mergeChanges
на сотрудника. В моей ситуации с двумя контекстами я все еще мог бы использовать этот метод, чтобы разорвать цикл в контексте Main, но как мне разорвать цикл в контексте Root?
Примечание: это простой пример для описания моей проблемы. В инструментах я ясно вижу, как растет количество выделений. В моем приложении контексты, которые выходят за пределы одного уровня, вызывают еще большую проблему, потому что я получаю новое выделение сущности с циклом сохранения для контекста I 'м экономия.
Обновление 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: Демонстрационный проектI '
Мы создали демо-проект: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];
}];
}];
Верхний нет освобождает объекты, нижний делает.