Каков надлежащий способ выгрузки представлений в iOS 6 в предупреждении памяти (ошибка Apple doc)?
В iOS 6, viewWillUnload
и viewDidUnload
устарели, а UIViewControllers больше не выгружают представления, которые не отображаются на экране во время предупреждения о памяти. В руководстве View Programmingler Programming Guide приведен пример того, как вручную восстановить это поведение.
Вот пример кода:
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Add code to clean up any of your own resources that are no longer necessary.
if ([self.view window] == nil)
{
// Add code to preserve data stored in the views that might be
// needed later.
// Add code to clean up other strong references to the view in
// the view hierarchy.
self.view = nil;
}
}
Ниже образца кода следует отметить следующее:
При следующем доступе к виду свойства вид перезагружается точно так же, как это было в первый раз.
Здесь есть очевидный недостаток. Если контроллер просмотра, который не загрузил его представление, получает предупреждение о сохранении памяти, он загрузит его вид в строке if ([self.view window] == nil)
, а затем продолжит очистку и отпустите его снова. В лучшем случае это неэффективно. В худшем случае это ухудшает условия памяти, если загружена сложная иерархия представлений и поддерживающие данные. Я проверил это поведение в симуляторе iOS.
Я могу, конечно, кодировать вокруг этого, но кажется, что для документов Apple есть странная ошибка. Я что-то пропустил?
Ответы
Ответ 1
Правильная проверка в контроллере представления для загружаемого представления и на экране:
if ([self isViewLoaded] && [self.view window] == nil)
Мое полное решение в iOS 6, чтобы иметь диспетчер разметки просмотра и очистки, подобный iOS 5, выглядит следующим образом:
// will not be called in iOS 6, see iOS docs
- (void)viewWillUnload
{
[super viewWillUnload];
[self my_viewWillUnload];
}
// will not be called in iOS 6, see iOS docs
- (void)viewDidUnload
{
[super viewDidUnload];
[self my_viewDidUnload];
}
// in iOS 6, view is no longer unloaded so do it manually
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
if ([self isViewLoaded] && [self.view window] == nil) {
[self my_viewWillUnload];
self.view = nil;
[self my_viewDidUnload];
}
}
- (void)my_viewWillUnload
{
// prepare to unload view
}
- (void)my_viewDidUnload
{
// the view is unloaded, clean up as normal
}