Память не освобождена в иерархии представлений ios - PullRequest
4 голосов
/ 05 января 2012

У меня есть iOS-приложение, которое использует ARC.Я не использую InterfaceBuilder, весь пользовательский интерфейс генерируется вручную.В этом приложении у меня есть несколько UIViewControllers с SubViewControllers.Те ViewControllers, связанные из меню (-ViewController), которые помещают их в стек.

Моя проблема в том, что память не освобождается при переключении между ViewControllers.

неправильно хранить ссылки на SubViewControllers как это?

@property (nonatomic, strong) UIViewController subViewController1; 
@property (nonatomic, strong) UIViewController subViewController2;

viewDidUnload никогда не вызывается.У кого-нибудь есть хороший пример того, как построить чистую иерархию представлений?

Ответы [ 2 ]

5 голосов
/ 06 января 2012

Присваивая контроллеры представления, которые помещаются в стек, сильной переменной / свойству экземпляра, они не будут освобождены, когда вытолкнуты из стека. Сильные свойства удерживают контроллеры push-представления даже после их выталкивания из стека, поэтому они никогда не попадают в состояние, в котором они могут быть освобождены.

Обычно, когда я помещаю контроллер представления следующего уровня в стек навигации, я делаю что-то вроде следующего:

SLSMoleculeSearchViewController *searchViewController = [[SLSMoleculeSearchViewController alloc] initWithStyle:UITableViewStylePlain];
[self.navigationController pushViewController:searchViewController animated:YES];

В ARC новый контроллер представления будет выделен и будет сохранен при создании. При перемещении в стек навигации он будет сохранен один раз контроллером навигации. Поскольку этот новый контроллер представления не упоминается после нажатия и не назначается сильному свойству или переменной экземпляра, ARC освободит его после второй строки.

Помните, навигационный контроллер все еще хранит его, поэтому он все еще хранится в памяти. Однако, как только навигационный контроллер вытолкнет его из стека, этот контроллер представления будет освобожден. Поскольку к этому моменту ничего не удерживается, оно будет освобождено, как и ожидалось.

Если по какой-то причине вам нужно сохранить ссылку на этот контроллер подчиненного представления в вашем контроллере представления более высокого уровня, вы можете использовать свойство weak или __weak переменную экземпляра. Это не будет держать на контроллере представления, и станет нулевым, как только контроллер будет освобожден.

weak ссылки поддерживаются только для приложений, ориентированных на iOS 5.0, поэтому вы не сможете сделать это для всего, что должно работать на iOS 4.0. 4.0-совместимое свойство unsafe_unretained - это не то, что я бы рекомендовал в этом случае из-за опасности указателя на освобожденную память.

0 голосов
/ 06 января 2012

Скорее всего, это не имеет ничего общего с ARC. viewDidUnload вызывается только в контроллере представления, когда свойство представления освобождается / устанавливается равным nil, и это обычно происходит только в том случае, если приложение получает предупреждение о памяти.

Попробуйте вызвать предупреждение памяти в симуляторе и посмотрите, не вызывает ли это ваш метод viewDidUnload. Если это так, то все в порядке. Если нет, то вы, вероятно, каким-то образом чрезмерно сохраняете свои представления, возможно, присваивая их другим сильно сохраненным свойствам.

Существуют исключения из политики сохранения представления, например, UINavigationController освобождает представления в своем стеке контроллера представления, если они не являются передними, но он делает это, просто устанавливая представление своих дочерних контроллеров в ноль, когда они ' покрыты взглядом другого контроллера.

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

...