Предотвращение создания зарегистрированного объекта (memleak) в NSManagedObjectContext - PullRequest
10 голосов
/ 22 июня 2011

У меня есть приложение для iOS, интенсивно использующее память, и я работаю над тем, чтобы использование памяти со временем не увеличивалось.У моего приложения есть «основной» контекст, который живет в течение всего срока службы приложения, при этом другие фоновые контексты иногда создаются для фоновых задач.

Одна вещь, которую я заметил, - это то, что NSManagedObjects, кажется, остаются зарегистрированными в основном контекстедолгосрочный и единственный способ по-настоящему восстановить всю память, связанную с извлечением объектов из БД, - это вызвать [NSManagedObjectContext reset].

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

Это единственный способ очистки зарегистрированного набора объектов из NSManagedObjectContext или естьлучшеспособ, который успешно удаляет все зарегистрированные объекты, на которые у вас больше нет ссылок, но не делает недействительными все NSManagedObjects, которые все еще живы?

1 Ответ

14 голосов
/ 24 июня 2011

NSManagedObjectContext имеет внутренний кеш строк, и единственный способ очистить это - сбросить контекст. Если у вас действительно возникают проблемы с памятью, вам могут помочь следующие вещи:

  • Управляемые объекты сохраняют связанные объекты. Если у вас есть управляемый объект A, на который ссылается связь какого-либо другого управляемого объекта B, то объект A останется в памяти, даже если вы освободили все ссылки на него. На самом деле он не будет освобожден до тех пор, пока объект B не будет освобожден или повторно поврежден, потому что он все еще будет сохраняться B.
  • Одним из способов решения этой проблемы (и других проблем с памятью) является вызов refreshObject:mergeChanges: в MOC для объектов, которые вы в данный момент не используете, со вторым аргументом, установленным в NO. Это приводит к повторному отказу объекта, то есть возвращает объект к исходному состоянию «сбой», выгружая значения его свойств и отношения. С A и B от предыдущих, повторное сбой B освободит отношение к A. Имейте в виду, что это приведет к потере всех несохраненных изменений на B, поэтому при необходимости сначала сохраните.
  • Если ваши управляемые объекты содержат большие двоичные данные, попробуйте переместить эти данные в отдельную сущность или из базовых данных, чтобы не загружать их в память, когда она не нужна.
  • reset в MOC - это в основном ядерный вариант, когда речь идет об управлении памятью Core Data. Это чрезвычайно эффективно, но, как вы обнаружили, может быть очень опасным. Лучше избегать этого, если вы не используете объекты, загруженные из MOC.
...