UIViewController -viewDidLoad не вызывается
Будучи новичком в Какао, у меня есть несколько проблем с Interface Builder
, UIViewController
и друзья.
у меня есть UIViewController
подкласс с UIView
определенный в xib, и с выходом вида контроллера, связанным с представлением. "Владелец файла" XIB установлен как подкласс myViewcontroller.
В этом случае следующий код для загрузки контроллера / представления (из контроллера основного представления) не работает должным образом:
if ( self.myViewController == nil )
{
self.myViewController = [[MyViewController alloc]
initWithNibName:@"MyViewController" bundle:nil];
}
[self.navigationController
pushViewController:self.myViewController animated:YES];
В методах MyViewController я разместил точки останова и регистрировал сообщения, чтобы увидеть, что происходит:
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
NSLog(@"initWithNibName\n");
}
return self;
}
-(void)viewDidLoad {
[super viewDidLoad];
NSLog(@"viewDidLoad\n");
}
Ожидаемый результат
И то и другое -initWithNibName
а также -viewDidLoad
методы вызываются, и отображается представление myViewController.
Наблюдаемый результат
Только -initWithNibName
называется, вид не отображается.
Я что-то пропустил? Кто-нибудь может порекомендовать что-нибудь проверить? (Особенно в удивительно непрозрачном инструменте Interface Builder).
11 ответов
Хорошо, у меня есть частичный ответ - может быть, гуру могут объяснить еще немного. Проблема в:
[self.navigationController pushViewController:myViewController animated:YES];
Если присмотреться, в этом случае self.navigationController
это ноль - так что push-сообщение не идет никуда.
Вместо этого, если я отправлю:
[self.view addSubview:self.myViewController.view];
Затем появляется вид и -viewDidLoad
называется.
Я не совсем уверен, почему self.navigationController
не установлен в этом случае - единственное, что я могу думать о том, что self
это подкласс UIViewController
скорее, чем UITableViewController
(где pushViewController
Код пришел).
Кроме того, молчаливое разрешение отправлять сообщения на ноль кажется плохой идеей, хотя эти ответы говорят об обратном. Смотрите также мой вопрос здесь.
Окончательное редактирование:
Ответы в комментариях ниже, я понял, что функция отображения, за которой я фактически следовал (учитывая, что myViewController является модальным):
[self presentModalViewController:myViewController animated:YES];
Спасибо всем за полезные ответы.
RE: РЕШЕНИЕ НАЙДЕНО!!!!!
Действительно, это кажется рабочим решением, однако реальная уловка не в том, чтобы view.hidden
свойство NO, что делает загрузку представления из nib-файла вызовом UIViewController's
Метод view, вид фактически загружается из пера только тогда, когда метод view вызывается впервые.
В этом смысле простой [viewController view]
сообщение заставит представление загрузить из файла пера.
РЕШЕНИЕ НАЙДЕНО!!!!!
Даже что-то столь безобидное, как это делает viewDidLoad
вызов метода происходит.
Вставьте это сразу после выделения initWithNibName
viewController.view.hidden = NO; //calls viewDidLoad
Убедитесь, что выход представления в "Владельце файла" (ваш подкласс viewController) подключен к фактическому представлению (т. е. холсту 480X320, который вы видите на экране и используете для создания пользовательского интерфейса).
Просто использовать
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
//Your Code here
}
вместо метода viewDidLoad.
Скорее всего, вы не связали предполагаемое ViewController
в main.storyboard
от Identity Inspector
к обычаю class
Вы создали Вы можете быть в состоянии перейти к этому контроллеру с других контроллеров представления через сегменты, но любой из viewDidLoad()
, viewWillAppear()
и т.д. не будут выполнены.
Еще одна причина, несколько очевидная в ретроспективе: если viewController.view
устанавливается в коде, тогда событие viewDidLoad не сработает.
Это похоже на проблему с капитализацией для меня. Вы ссылаетесь на класс MyViewController
вместо собственности myViewController
в вызове pushViewController.
Проверьте журнал выполнения на наличие ошибок. Почти наверняка, NIB не загружается, и должна быть ошибка на этот счет. Наиболее вероятной причиной этого является невозможность положить его в комплекте. Посмотрите на этапе сборки "Копирование ресурсов" и убедитесь, что XIB действительно копируется. Выполните сборку для симулятора, зайдите в каталог сборки и убедитесь, что NIB находится в комплекте.app.
Помимо других ответов здесь,
Это часто случается, когда идентификатор, с которым вы создаете экземпляр ViewController из раскадровки, неверен. Например,
[[self getStoryboard] instantiateViewControllerWithIdentifier:MyVC];
Если MyVC
- это идентификатор какого-либо другого ViewController, такое может случиться.
OP использует nib
вместо раскадровки здесь. Но ответ применим.
Страница была представлена, но не видна в иерархии представления отладки и в устройстве (также в симуляторе), проблема возникает на основе, и я нашел исправление:
func viewWillLayoutSubviews{
if day == true{
self.view.backgroundColor = .clear
}else{
self.view.backgroundColor = .blue
}
}
Не пытайтесь реализовать self.view (представление viewcontrollers) в функции layoutsubviews. Так что лучше используйте self.view в viewwillappear или viewdidload. Эта проблема возникает начиная с устройств v-14.
Надеюсь, это сработает и для вас.