Невозможно правильно установить кадр перед viewDidAppear
Мне было интересно, знает ли кто-нибудь, почему, когда вы устанавливаете кадр подвью в viewDidLoad
и viewWillAppear
, изменения не влияют на экран, но если вы установите его в viewDidAppear
, то они делают?
В моем случае я загружаю пользовательский xib с двумя табличными представлениями, а затем пытаюсь переместить их в viewDidLoad
, чтобы разрешить пространство для другого представления, которое добавлено в viewDidLoad
, поскольку его не всегда необходимо отображать.
Проблема заключается в том, что я устанавливаю фрейм в viewDidLoad
или viewWillAppear
, который он задает на объекте, я вижу, распечатывая его, но он не отображается на экране. Перемещение звонков с установленным кадром на viewDidAppear
приведет к тому, что все будет работать как ожидалось.
Неправильно ли мне думать, что я должен установить кадр в viewDidLoad
?
- (id)init {
if ( self = [super initWithNibName:@"MyView" bundle:nil] ) {}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.descriptionWebView = [[[UIWebView alloc] initWithFrame:CGRectMake( 0, 0, self.view.frame.size.width, 200 )] autorelease];
[self.view addSubview:self.descriptionWebView];
self.tableView1.autoresizingMask = UIViewAutoresizingNone;
self.tableView2.autoresizingMask = UIViewAutoresizingNone;
[self.descriptionWebView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"...." withExtension:@"html"]]];
table1LocationWithHeader = CGRectMake( self.tableView1.frame.origin.x, 200, self.tableView1.frame.size.width, self.tableView1.frame.size.height - 200 );
table2LocationWithHeader = CGRectMake( self.tableView2.frame.origin.x, 200, self.tableView2.frame.size.width, self.tableView2.frame.size.height - 200 );
//this will NOT work
self.tableView1.frame = table1LocationWithHeader;
self.tableView2.frame = table2LocationWithHeader;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//this will NOT work
self.tableView1.frame = table1LocationWithHeader;
self.tableView2.frame = table2LocationWithHeader;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//this WILL work
self.tableView1.frame = table1LocationWithHeader;
self.tableView2.frame = table2LocationWithHeader;
}
//I added these after comments for Qaru users, it seems like viewDidLayoutSubviews is the best place to set the frame
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
//this will NOT work
self.tableView1.frame = table1LocationWithHeader;
self.tableView2.frame = table2LocationWithHeader;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
//this WILL work
self.tableView1.frame = table1LocationWithHeader;
self.tableView2.frame = table2LocationWithHeader;
}
Ответы
Ответ 1
viewDidLoad вызывается, когда класс загружен, однако никакие элементы ui не были инициализированы, и поэтому любая попытка их ссылки будет перезаписана или недоступна во время процесса инициализации, который происходит между вызовами viewDidLoad и viewDidAppear. После того, как все элементы ui были инициализированы и нарисованы viewDidAppear, вызывается.
viewDidLoad - Вызывается, когда представление контроллера загружается в память
В этот момент представление не находится в иерархии представлений.
viewWillAppear - уведомляет контроллер представления о том, что его представление будет добавлено в иерархию представлений.
Опять же, представление еще не добавлено в иерархию представлений.
viewDidAppear - уведомляет контроллер представления о том, что его представление было добавлено в иерархию представлений.
Только тогда представление добавляется в иерархию представления.
Обновление
viewDidLayoutSubviews
является наиболее подходящим местом для изменения пользовательского интерфейса перед его фактическим отображением на экране.
viewDidLayoutSubviews - уведомляет контроллер представления о том, что его представление просто выложило его подпрограммы.
Ответ 2
Посмотрите эту тему Когда вызывается макетSubviews?
При использовании автозапуска фреймворк автоматически не вызывает layoutSubviews. Это очень важно. Из ссылки:
- init не вызывает вызов layoutSubviews (duh)
- addSubview: вызывает отображение layoutSubviews в добавляемом представлении, представление его добавляется в (целевой вид) и все подчиненные объекты цели....
Если вы добавляете subview в viewDidLoad, layoutSubviews вызывается перед viewDidAppear, и вы можете получить правильный размер subviews. Но если вы ничего не сделаете, layoutSubviews вызывается после viewDidAppear. Это до вашего кода.
Ответ 3
в viewWillAppear()
просто вызовите layoutIfNeeded() один раз для представления, чей кадр вы хотите получить.
если tableView затем tableView.layoutIfNeeded() для exmple