ViewDidLoad и awakeFromNib
Я понимаю, что awakeFromNib всегда будет вызываться перед viewDidLoad.
Итак, у меня есть подкласс UITableViewController, который не имеет аналогов из файла xib.
Я определил эти два метода внутри:
- (void)awakeFromNib {
[super awakeFromNib];
NSLog(@"awake from nib");
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"view did load");
}
происходит то, что "view did load" появляется до "awake from nib" в консоли. Я попытался использовать точку останова на [super awakeFromNib] и многократно нажимал F7 (Step Into), и, к моему удивлению, он вступил в (void) viewDidLoad ПЕРЕД ПЕРЕД прохождением ко второй строке в awakeFromNib.
Кто-нибудь знает, что здесь происходит? Я сделал то же самое в подклассе обычного UIViewController, и операторы журнала меняются на противоположные, как я и ожидал...
Ответы
Ответ 1
Чтобы понять этот факт, я рекомендую вам loadNibNamed:owner:options:
метод NSBundle
.
Когда вы запускаете контроллер вида из nib, в первую очередь он загружает просмотры, которые там содержатся, то он устанавливает свойства файлов в соответствии с nib. Метод viewDidLoad
вызывается, когда он устанавливает свойство владельца файла view
в одно из видов, которые были загружены. И awakeFromNib
вызывается, когда установлены все фиды и свойства файлов (включая свойство view
). Поэтому имеет смысл, что viewDidLoad
вызывается раньше awakeFromNib
.
Надеюсь, что это поможет
Ответ 2
Я создаю тестовый проект с опцией Приложения на основе навигации и добавляю следующие коды в rootViewController.m.
- (void)awakeFromNib {
NSLog(@"awakeFromNib 1");
[super awakeFromNib];
NSLog(@"awakeFromNib 2");
}
- (void)viewDidLoad {
NSLog(@"viewDidLoad 1");
[super viewDidLoad];
NSLog(@"viewDidLoad 2");
}
Затем я получил результаты из консоли:
awakeFromNib 1
awakeFromNib 2
viewDidLoad 1
viewDidLoad 2
-(void)viewDidLoad
будет вызываться при загрузке представления контроллера. Таким образом, когда вы впервые используете self.view =...
, будет вызываться -(void)viewDidLoad
.
Если вы написали что-то вроде следующего, тогда -(void)viewDidLoad
будет вызван первым.
- (void)awakeFromNib {
NSLog(@"awakeFromNib 1");
// The log sequence will be funny, if 'viewDidLoad' raised before [super awakeFromNib]
// If you are curios about it, just give it a try.
// self.view.backgroundColor = [UIColor clearColor];
[super awakeFromNib];
/// viewDidLoad will be called
/// because self.view must be loaded first.
self.view.backgroundColor = [UIColor clearColor];
NSLog(@"awakeFromNib 2");
}
и получить следующие результаты.
awakeFromNib 1
viewDidLoad 1
viewDidLoad 2
awakeFromNib 2
Обновить
loadViewIfNeeded вызовет viewDidLoad
если загрузит представление успешно. Иногда я буду вызывать loadViewIfNeeded, чтобы убедиться, что экземпляры @IBOutlet
были инициализированы и больше не @IBOutlet
нулю.
Ответ 3
Я не думаю, что вам нужно вызвать awakeFromNib в своем суперклассе.
Отметьте этот.
Edit
Я только что проверил быстрый тест, вот результаты:
Сценарий 1:
MainWindow.Xib имеет подкласс UIViewController TestingAwakeFromNibViewController
, у которого есть собственный файл Nib TestingAwakeFromNibViewController.xib
.
TestingAwakeFromNibViewController имеет выход UIButton, называемый btn3.
Тестирование следующего кода:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"Btn3 %@",btn3);
NSLog(@"viewDidLoad");
}
-(void) awakeFromNib
{
[super awakeFromNib];
NSLog(@"Btn3 %@",btn3);
NSLog(@"awakeFromNib");
}
Будет печать:
Btn3 (null)
AwakeFromNib
Btn3 <UIRoundedRectButton: 0x64088e0; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x6408890>>
ViewDidLoad
Сценарий 2:
Удаление xib файла, добавление UIView в качестве сына в TestingAwakeFromNibViewController внутри MainWindow.Xib и добавление UIButton в качестве подпрограммы UIView (и подключение выхода UIbutton к соответствующему выходу TestingAwakeFromNibViewController).
Теперь выполняемый выше код будет печатать:
Btn3 <UIRoundedRectButton: 0x4e31c30; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e31be0>>
viewDidLoad
Btn3 <UIRoundedRectButton: 0x4e31c30; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e31be0>>
awakeFromNib
Значение ViewDidLoad до AwakeFromNib.
Третий сценарий:
То же, что и второе, без вызова [super awakeFromNib];
Btn3 <UIRoundedRectButton: 0x4e0ddf0; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e0dda0>>
awakeFromNib
Теперь ViewDidLoad даже не вызван.
Итак, похоже, что разные сценарии требуют различного действия, и нам нужно подготовиться к тому, с чем мы действуем.
Ответ 4
Не будучи экспертом и следуя этим сообщениям, я понимаю, чем в сценарии с контроллером табуляции. В "дочернем" контроллере представлений метод awakeFromNib выполняется при загрузке контроллера табуляции (родителя), но viewDidLoad только тогда, когда его "Tab".
И поэтому я понимаю, что это можно использовать для загрузки данных только тогда, когда выбрана конкретная вкладка (нажата)