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

Невозможно правильно установить кадр перед 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;
}
4b9b3361

Ответ 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