Как часто вызывается viewDidLoad? - PullRequest
20 голосов
/ 04 февраля 2012

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

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

Ответы [ 5 ]

29 голосов
/ 04 февраля 2012

Не выполнять просмотр инициализации контроллера в viewDidLoad.Это распространенная ошибка.

Для вещей, которые должны происходить только один раз при загрузке контроллера представления, сделайте это в методе init контроллера, например:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)bundleOrNil
{
    if ((self = [super initWithNibName:nibNameOrNil bundle:bundleOrNil]))
    {
        //do your initialisation here
    }
    return self;
}

initWithNibName:bundle:метод вызывается до представление загружается из пера, и вызывается только один раз в течение срока службы контроллера представления.

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

Если вы настраиваете вещи в viewDidLoad (например, добавляете подпредставления программно), вы всегда должны сбрасывать их снова в viewDidUnload.

Думайте о viewDidLoad и viewDidUnload как о init / dealloc для свойства view контроллера представления.Для материала, который относится к представлениям, создайте и отпустите его в этих методах.Для вещей, которые относятся к самому контроллеру, создайте и выпустите его в initWithNibName и dealloc.

ОБНОВЛЕНИЕ: В iOS 6 и более поздних версиях viewDidUnload больше никогда не вызывается(если в коде явно не установлено представление), и поэтому viewDidLoad обычно вызывается только один раз в жизни контроллера представления.Это делает приведенные выше рекомендации менее критичными, но все же это лучшая практика, и она по-прежнему необходима, если вам требуется поддержка iOS 5 и более ранних версий.

ОБНОВЛЕНИЕ 2: Если вы загружаете контроллер представления изРаскадровка (которая сейчас является рекомендуемой практикой) вместо того, чтобы создавать ее программно, тогда initWithNibName:bundle: не будет вызываться.Используйте initWithCoder: или awakeFromNib для инициализации вашего контроллера.

17 голосов
/ 04 февраля 2012

@ Ник Локвуд предоставляет отличную информацию, но есть еще несколько вещей, которые нужно запомнить.

Во-первых, initWithNibName:bundle: не вызывается, если создается экземпляр контроллера представления из файла пера или раскадровки. В этом случае initWithCoder: и awakeFromNib вызываются вместо этого. Раньше такая ситуация была несколько необычной для iOS, но с добавлением раскадровок теперь гораздо чаще для контроллеров представления обходить initWithNibName:bundle:.

Я рекомендую поместить код инициализации не-пользовательского интерфейса в отдельный метод (я называю мой setup) и вызывать его как из initWithNibName:bundle:, так и awakeFromNib. Но я делаю это только в том случае, если важно, чтобы инициализация выполнялась только один раз. В противном случае я помещаю это в viewWillAppear:, чтобы быть как можно более ленивым.

Во-вторых, вы не должны делать ничего, что ссылается на self.view в init... или awakeFromNib. Вы никогда не должны ссылаться на self.view до тех пор, пока не будет вызван viewDidLoad (иначе вы заставите файл пера загружаться раньше, чем это необходимо). Вещи, связанные с пользовательским интерфейсом, должны входить в viewDidLoad, если они связаны с настройкой представлений, или viewWillAppear:, если они связаны с настройкой представлений (т.е. загружать их данными).

Итак, как я обычно это настраиваю:

@implementation

 - (void)setup {
  // Non-UI initialization goes here. It will only ever be called once.
}

- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle {
  if ((self = [super initWithNibName:nibName bundle:bundle])) {
    [self setup];
  }

  return self;
}

- (void)awakeFromNib {
  [self setup];
}

- (void)viewDidLoad {
  // Any UI-related configuration goes here. It may be called multiple times, 
  // but each time it is called, `self.view` will be freshly loaded from the nib
  // file.
}

- (void)viewDidUnload {
  [super viewDidUnload];
  // Set all IBOutlets to `nil` here.
  // Drop any lazy-load data that you didn't drop in viewWillDisappear:
}

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  // Most data loading should go here to make sure the view matches the model
  // every time it's put on the screen. This is also a good place to observe
  // notifications and KVO, and to setup timers.
}

- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  // Unregister from notifications and KVO here (balancing viewWillAppear:).
  // Stop timers.
  // This is a good place to tidy things up, free memory, save things to
  // the model, etc.
}

- (void)dealloc {
  // standard release stuff if non-ARC
  [[NSNotificationCenter defaultCenter] removeObvserver:self]; // If you observed anything
  // Stop timers.
  // Don't unregister KVO here. Observe and remove KVO in viewWill(Dis)appear.
}

@end
5 голосов
/ 04 февраля 2012

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

(Выше из оп)

В этих случаях нужно вызвать два метода:

- (void)applicationWillEnterForeground:(UIApplication *)application;

повторное открытие фонового приложения (из диспетчера задач или снова из трамплина)
разблокировка устройства, которое заблокировано, когда приложение активно.

- (void)applicationDidBecomeActive:(UIApplication *)application

после телефонных звонков
Центр уведомления об увольнении
увольнение диспетчера задач (двойное нажатие кнопки «Домой» и повторное двойное нажатие)

5 голосов
/ 04 февраля 2012

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

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

3 голосов
/ 04 февраля 2012

С документы :

Этот метод вызывается после того, как контроллер представления загрузил связанные виды в память.

Таким образом, он вызывается всякий раз, когда в контроллер представления загружаются его представления в память. Это может быть первый раз, когда представление загружается и никогда больше, или каждый раз, когда представление становится видимым, если ваше представление выгружается постоянно (viewDidUnload из-за ограничений памяти и т. Д.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...