Невозможно правильно установить кадр перед viewDidAppear

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

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

проблема в том, когда я устанавливаю frame в 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 stack overflow 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;
}

3 ответов


viewDidLoad вызывается при загрузке класса, однако никакие элементы пользовательского интерфейса не были инициализированы, и поэтому любая попытка ссылаться на них будет перезаписана или недоступна во время процесса инициализации, который происходит между вызовами viewDidLoad и viewDidAppear. После того как все элементы интерфейса были initalised и тянет viewDidAppear называется.

метод viewDidLoad - Вызывается после загрузки представления контроллера в память

в этот момент представление не входит в иерархию представлений.

viewWillAppear-уведомляет контроллер представления о том, что его представление будет добавлено в иерархию представлений.

опять же, представление еще не добавлено в иерархию представлений.

viewDidAppear-уведомляет контроллер представления о том, что его представление было добавлено в иерархию представлений.

только тогда представление добавляется в представление иерархия.

обновление

на viewDidLayoutSubviews является наиболее подходящим местом для изменения пользовательского интерфейса, прежде чем он фактически появится на экране.

viewDidLayoutSubviews-уведомляет контроллер вида, что его представление только что выложило свои подвиды.


смотрите здесь когда вызывается layoutSubviews?
при использовании autolayout framework не вызывает layoutSubviews автоматически. Это очень важно. От Реф:

  • init не вызывает layoutSubviews для вызова (duh)
  • addSubview: вызывает layoutSubviews для добавляемого представления, представления, в которое оно добавляется (целевое представление), и всех подвидов цели. ...


Если вы добавляете subview в viewDidLoad, layoutSubviews вызывается перед viewDidAppear, и вы можете получить правильный размер подвидов. Но если вы ничего не делаете, layoutSubviews будет вызываться после viewDidAppear. Это зависит от вашего кода.


в viewWillAppear()

просто вызовите layoutIfNeeded () один раз для представления, кадр которого вы хотите получить.

Если tableView, то tableView.layoutIfNeeded() для exmple