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

Как часто называется viewDidLoad?

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

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

Во-вторых, вы не должны делать ничего, что ссылается на self.view в init... или awakeFromNib. Вы не должны ссылаться на self.view до тех пор, пока не будет вызван viewDidLoad (в противном случае вы заставите файл nib загружаться раньше, чем это необходимо). Объекты, связанные с UI, должны находиться в 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 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

Ответ 3

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

(Выше из op)

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

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

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

- (void)applicationDidBecomeActive:(UIApplication *)application

после телефонных звонков
увольнение центра уведомлений
увольнение менеджера задачи (дважды нажмите кнопку "домой" и снова дважды нажмите)

Ответ 4

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

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

Ответ 5

Из документы:

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

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