Возразите пожизненному управлению
Жизненный цикл данных, которые представляет управляемый объект, в основном независим от времени жизни отдельных экземпляров управляемого объекта. Для добавления записи на персистентное хранилище необходимо выделить и инициализировать управляемый объект — и затем сохранить контекст управляемого объекта. При удалении записи из персистентного хранилища необходимо гарантировать, что в конечном счете освобожден его соответствующий управляемый объект. Промежуточный эти события, однако, можно создать и уничтожить любое число экземпляров управляемого объекта, представляющих ту же запись в данном персистентном хранилище.
Роль контекста управляемого объекта
Управляемые объекты знают, с каким контекстом управляемого объекта они связаны, и контексты управляемого объекта знают, какие управляемые объекты они содержат. По умолчанию, тем не менее, ссылки между управляемым объектом и его контекстом слабы. Это означает, что в целом Вы не можете полагаться на контекст для обеспечения долговечности экземпляра управляемого объекта, и Вы не можете полагаться на существование управляемого объекта гарантировать долговечность контекста. Другими словами просто потому что Вы выбрали объект, не означает, что это останется вокруг.
Исключение к этому правилу - то, что контекст управляемого объекта поддерживает сильную ссылку любому измененному (вставленный, удаленный и обновленный) объекты, пока отложенная транзакция не фиксируется (с a save:
) или отброшенный (с a reset
или rollback
). Обратите внимание на то, что менеджер по отмене может также сохранить сильные ссылки к измененным объектам — посмотрите управление Изменением и Отменой.
Можно изменить поведение контекста по умолчанию, таким образом, что оно действительно сохраняет сильные ссылки к своим управляемым объектам путем отправки ему a setRetainsRegisteredObjects:
сообщение (с параметром YES
) — это заставляет времена жизни управляемых объектов зависеть от контекста. Это может быть удобством при кэшировании меньших наборов данных в памяти — например, если контекст управляет временным набором объектов, которые могут сохраниться вне единственного цикла события, такой, редактируя в листе. Если Вы выполняете фоновую выборку и передаете идентификаторы объектов основному потоку, может также быть полезно при использовании многократных потоков и передающих данных между ними — например. Фоновый поток должен сохранить сильные ссылки к объектам, которые он выбрал с упреждением для основного потока, пока он не знает, что основной поток фактически использовал идентификаторы объектов для сбоя локальных экземпляров в себя.
Необходимо обычно использовать отдельный контейнер для хранения сильных ссылок только теми управляемыми объектами, в которых Вы действительно нуждаетесь. Можно использовать массив или словарь или объектный контроллер (например, NSArrayController
экземпляр), который имеет сильные ссылки объекты, которыми он управляет. Управляемые объекты, в которых Вы не нуждаетесь, будут тогда освобождены, когда возможный (например, когда отношения очищены).
Если Вы закончили с контекстом управляемого объекта, или по некоторой другой причине Вы хотите «разъединить» контекст от его персистентного координатора хранилища, Вы не должны устанавливать координатора контекста в nil
:
// This will raise an exception. |
[myManagedObjectContext setPersistentStoreCoordinator:nil]; |
Вместо этого необходимо просто оставить владение контекста и позволить ему обычно освобождаться.
Повреждение циклов сильной ссылки отношения
Когда у Вас есть отношения между управляемыми объектами, каждый объект поддерживает сильную ссылку к объекту или возражает, с которым это связано. Это может вызвать циклы сильной ссылки. Чтобы гарантировать, что ссылочные циклы повреждаются, когда Вы закончены с объектом, можно использовать метод контекста управляемого объекта refreshObject:mergeChanges:
превратить его в отказ.
Вы обычно используете refreshObject:mergeChanges:
обновить значения свойств управляемого объекта. Если mergeChanges
флаг YES
, метод объединяет значения свойств объекта с теми из объекта, доступного в персистентном координаторе хранилища. Если флаг NO
, однако, метод просто возвращает объект в отказ без слияния, заставляющего его повреждать сильные ссылки к связанным управляемым объектам. Это повреждает цикл сильной ссылки между тем управляемым объектом и другими управляемыми объектами.
Обратите внимание на то, что, конечно, прежде чем управляемый объект может быть освобожден не должно быть никаких сильных ссылок к нему, включая от за пределами Базовых Данных. См. также управление Отменой и Изменение.
Изменение и управление отменой
Контекст сохраняет сильные ссылки к управляемым объектам, имеющим незаконченные изменения (вставки, удаления или обновления), пока контекст не отправляется a save:
, reset
, rollback
, или dealloc
сообщение или надлежащее число неDOS для отмены изменения.
Менеджер по отмене, связанный с контекстом, сохраняет сильные ссылки к любым измененным управляемым объектам. По умолчанию в OS X менеджер по отмене контекста сохраняет неограниченную отмену/стек повторного выполнения. Для ограничения объема потребляемой памяти приложения необходимо удостовериться, что Вы вычищаете (использование removeAllActions
) стек отмены контекста как и, когда надлежащий. Если Вы не сохраняете сильную ссылку менеджеру по отмене контекста, она освобождена с ее контекстом.
Если Вы не намереваетесь использовать функциональность отмены Базовых Данных, можно сократить требования к ресурсам приложения путем установки менеджера по отмене контекста в nil
. Это может быть особенно выгодно для фоновых рабочих потоков, а также для большого импорта или пакетных обработок.