Подтвердить что ты не робот

IOS 6 - viewDidUnload перейти на didReceiveMemoryWarning?

Итак, с viewDidUnload, устаревшим с iOS 6, что мне нужно сделать сейчас?

Удалить его и перенести все содержимое в didReceiveMemoryWarning или оставить его и ничего не делать в didReceiveMemoryWarning?

4b9b3361

Ответ 1

Короткий ответ заключается в том, что во многих случаях вам ничего не нужно менять. И вы, безусловно, не хотите просто переносить все содержимое viewDidUnload на didReceiveMemoryWarning.

Как правило, большинство из нас делают настройку IBOutlet ссылок на nil в viewDidUnload (в основном потому, что Interface Builder поставит это для нас) и сделать общее освобождение памяти (например, очистка кешей, освобождение легко воссозданных данных модели и т.д.) в didReceiveMemoryWarning. Если это так, как вы это делаете, вы, вероятно, не нуждаетесь в каких-либо изменениях кода.

Согласно документации iOS 6 viewDidUnload:

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

Следовательно, вы не хотите перемещать настройки своих IBOutlet ссылок на nil в любом месте, потому что представления больше не очищаются. Нет смысла устанавливать их в nil в didReceiveMemoryWarning или что-то в этом роде.

Но если вы отвечали на события с низкой памятью, выпуская легко обновленные объекты модели, опустошив кеши и т.д. в viewDidUnload, тогда этот материал обязательно должен перейти на didReceiveMemoryWarning. Но потом, опять же, большинство из нас уже там уже было.

Наконец, если вы освободите что-либо в didReceiveMemoryWarning, просто убедитесь, что ваш код не полагается на то, что они снова воссоздаются в viewDidLoad, когда вы выскакиваете назад, потому что это не будет вызываться (поскольку сам вид, никогда не выгружался).

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

Ответ 2

Короткий ответ:

Никогда не используйте -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:

Это время жизни viewController (строки, выделенные курсивом, означают, что эти методы могут быть вызваны несколько раз):

  • init: ViewController загружен, еще нет элемента интерфейса (IBOutlet) (все ноль)
  • viewDidLoad: загружена nib/раскадровка и доступны все объекты. Пользователь еще ничего не видит
  • viewWillAppear: представление будет отображаться
  • viewDidAppear: вид на экране
  • viewWillDisappear: представление вот-вот исчезнет.
  • viewDidDisappear: вид только что снят с окна
  • viewDidUnload: НИКОГДА НЕ ЗВОНО в iOS6/7
  • didReceiveMemoryWarning: вы не знаете, если, когда и как часто это называется. До iOS6 он может выгрузить представление, после того как iOS6 просто очистит внеэкранный кеш или ничего не делает
  • dealloc: viewController собирается уничтожить

Итак, чтобы подвести итог, есть различные возможности; то, что сейчас происходит, действительно зависит от того, что было инициализировано, где:

  • -dealloc, если он создан в -init: или -viewDidLoad:
  • -viewWill/DidDisappear (в паре с -viewWill/DidAppear)
  • -didReceiveMemoryWarning (может и не вызываться)

Ответ 3

Если вам нужно знать, отклоняется ли ваш UIViewController, вы можете добавить этот код в свой видWillDisappear:

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    if ([self isBeingDismissed] || [self isMovingFromParentViewController])
    {
        // Do your viewDidUnload stuff
    }
}

Он не вызывается одновременно с тем, как viewDidUnload сделал один раз в жизненном цикле контроллера просмотра, но работает в большинстве случаев для ваших нужд!

Ответ 4

Зависит от того, что вы делаете в viewDidUnload, но вы можете использовать didReceiveMemoryWarning или dealloc для выпуска данных. См. .

Ответ 5

В большинстве типичных случаев этот метод можно использовать вместо старого 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)
}