Итак, с viewDidUnload
, устаревшим с iOS 6, что мне нужно сделать сейчас?
Удалить его и перенести все содержимое в didReceiveMemoryWarning
или оставить его и ничего не делать в didReceiveMemoryWarning
?
Итак, с viewDidUnload
, устаревшим с iOS 6, что мне нужно сделать сейчас?
Удалить его и перенести все содержимое в didReceiveMemoryWarning
или оставить его и ничего не делать в didReceiveMemoryWarning
?
Короткий ответ заключается в том, что во многих случаях вам ничего не нужно менять. И вы, безусловно, не хотите просто переносить все содержимое viewDidUnload
на didReceiveMemoryWarning
.
Как правило, большинство из нас делают настройку IBOutlet
ссылок на nil
в viewDidUnload
(в основном потому, что Interface Builder поставит это для нас) и сделать общее освобождение памяти (например, очистка кешей, освобождение легко воссозданных данных модели и т.д.) в didReceiveMemoryWarning
. Если это так, как вы это делаете, вы, вероятно, не нуждаетесь в каких-либо изменениях кода.
Согласно документации iOS 6 viewDidUnload
:
Представления больше не очищаются в условиях низкой памяти, поэтому этот метод никогда не вызывается.
Следовательно, вы не хотите перемещать настройки своих IBOutlet
ссылок на nil
в любом месте, потому что представления больше не очищаются. Нет смысла устанавливать их в nil
в didReceiveMemoryWarning
или что-то в этом роде.
Но если вы отвечали на события с низкой памятью, выпуская легко обновленные объекты модели, опустошив кеши и т.д. в viewDidUnload
, тогда этот материал обязательно должен перейти на didReceiveMemoryWarning
. Но потом, опять же, большинство из нас уже там уже было.
Наконец, если вы освободите что-либо в didReceiveMemoryWarning
, просто убедитесь, что ваш код не полагается на то, что они снова воссоздаются в viewDidLoad
, когда вы выскакиваете назад, потому что это не будет вызываться (поскольку сам вид, никогда не выгружался).
Как говорит applefreak, это зависит от того, что вы делали в viewDidUnload
. Если вы обновите свой вопрос с явных примеров того, что у вас было в viewDidUnload
, мы можем, возможно, предоставить менее абстрактные советы.
Короткий ответ:
Никогда не используйте -didReceiveMemoryWarning для сбалансированного срыва, так как его можно вызвать никогда или несколько раз. Если у вас установлена ваша установка в -viewDidLoad, поместите код очистки в -dealloc.
Длинный ответ:
Нелегко дать общий ответ, так как это действительно зависит от ситуации. Однако есть два важных факта:
1. -viewDidUnload устарел и на самом деле никогда не звонил, начиная с iOS6 и позже. Итак, если у вас есть код очистки, ваше приложение течет под этими версиями ОС
2. -didReceiveMemoryWarning может вызываться несколько раз или никогда. Это действительно плохое место для сбалансированного удаления объектов, которые вы создали где-то еще.
В моем ответе рассматривается общий случай, когда вы используете свойства, например:
@property (strong) UIView *myCustomView // <-- this is what I'm talking about
@property (assign) id *myDelegate
Здесь вам нужно сделать некоторую очистку, потому что вы либо создали, либо создали собственный интерфейс CustomView или InterfaceBuilder, но сохранили его. До iOS 6 вы, вероятно, сделали бы что-то вроде этого:
- (void)viewDidLoad {
self.myCustomView = [[UIView alloc] initWithFrame:…];
}
- (void)viewDidUnload { // <-- deprecated!
[myCustomView removeFromSuperView];
self.myCustomView = nil;
}
... потому что (снова) myCustomView
является сохраненным свойством, созданным и принадлежащим вам, и поэтому вам нужно позаботиться и "освободить" его (установить его на нуль) в конце.
С iOS 6 лучшим местом для замены -viewDidUnload
и для сохранения сохраняемого свойства является nil, вероятно, -dealloc
. Там также viewWillAppear
и viewDidDisappear
, но они не привязаны к жизненному циклу вашего представления/контроллера, но цикл отображения (С другой стороны, методы -... идеально подходят для отказа/регистрации прослушивателей уведомлений!). Поэтому было бы нецелесообразно создавать и уничтожать представления до и после каждого отображения. dealloc
- единственный метод, который мы можем быть уверены в том, чтобы быть вызванным в самом конце жизненного цикла контроллера. Обратите внимание, что вы не должны вызывать [super dealloc]
, если вы используете ARC:
- (void)dealloc {
self.myCustomView = nil;
}
Однако, если вы используете viewDidLoad
для создания некоторой связанной с просмотром установки, которая может быть освобождена при условиях низкой памяти, другие сообщения, показывающие, как справляться с ситуациями с низкой памятью, являются полностью действительными. В этом случае вы также можете использовать dealloc, но вы должны проверить, остались ли ваши мнения.
Может быть, также полезно посмотреть общий жизненный цикл ViewController:
Это время жизни viewController (строки, выделенные курсивом, означают, что эти методы могут быть вызваны несколько раз):
- init: ViewController загружен, еще нет элемента интерфейса (IBOutlet) (все ноль)
- viewDidLoad: загружена nib/раскадровка и доступны все объекты. Пользователь еще ничего не видит
- viewWillAppear: представление будет отображаться
- viewDidAppear: вид на экране
- viewWillDisappear: представление вот-вот исчезнет.
- viewDidDisappear: вид только что снят с окна
- viewDidUnload: НИКОГДА НЕ ЗВОНО в iOS6/7
- didReceiveMemoryWarning: вы не знаете, если, когда и как часто это называется. До iOS6 он может выгрузить представление, после того как iOS6 просто очистит внеэкранный кеш или ничего не делает
- dealloc: viewController собирается уничтожить
Итак, чтобы подвести итог, есть различные возможности; то, что сейчас происходит, действительно зависит от того, что было инициализировано, где:
Если вам нужно знать, отклоняется ли ваш UIViewController, вы можете добавить этот код в свой видWillDisappear:
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if ([self isBeingDismissed] || [self isMovingFromParentViewController])
{
// Do your viewDidUnload stuff
}
}
Он не вызывается одновременно с тем, как viewDidUnload сделал один раз в жизненном цикле контроллера просмотра, но работает в большинстве случаев для ваших нужд!
Зависит от того, что вы делаете в viewDidUnload
, но вы можете использовать didReceiveMemoryWarning
или dealloc
для выпуска данных. См. .
В большинстве типичных случаев этот метод можно использовать вместо старого viewDidUnload.
// The completion handler, if provided, will be invoked after the dismissed controller viewDidDisappear: callback is invoked.
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion NS_AVAILABLE_IOS(5_0);
Синтаксис Swift 2017:
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
if (yourChildViewController != nil) {
print("good thing we did this!")
}
yourChildViewControllerProperty = nil
super.dismiss(animated: flag, completion: completion)
}