无法在viewDidAppear之前正确设置框架

我想知道如果有人知道为什么当你在viewDidLoadviewWillAppear设置子视图的框架的变化不会影响在屏幕上,但如果你设置它在viewDidAppear他们呢?

在我的情况下,我加载了一个自定义xib有两个tableviews,然后尝试在viewDidLoad移动它们,以允许在viewDidLoad添加另一个视图的空间,因为它并不总是需要显示它。

问题是,当我设置viewDidLoadviewWillAppear它在对象上设置框架,我可以看到通过打印出来,但它不反映在屏幕上。 将设置的框架调用移动到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; } 

当类加载时调用viewDidLoad,但是没有UI元素被初始化,因此在viewDidLoad和viewDidAppear调用之间的初始化过程中,任何尝试引用它们的尝试都将被覆盖或者不可避免。 一旦所有的UI元素都被初始化并绘制viewDidAppear被调用。

viewDidLoad – 在控制器视图加载到内存之后调用

此时视图不在视图层次结构中。

viewWillAppear – 通知视图控制器其视图即将被添加到视图层次结构中。

同样,视图还没有被添加到视图层次结构中。

viewDidAppear – 通知视图控制器其视图已添加到视图层次结构中。

只有这样才能将视图添加到视图层次结构中。

更新

viewDidLayoutSubviews是实际出现在屏幕上之前修改UI的最合适的地方。

viewDidLayoutSubviews – 通知视图控制器,它的视图只是布局它的子视图。

看到这个线程什么时候layoutSubviews被调用?
当使用自动布局时,框架不会自动调用layoutSubviews。 这非常重要。 从ref:

  • init不会导致layoutSubviews被调用(duh)
  • addSubview:使layoutSubviews在被添加的视图,被添加到的视图(目标视图)和目标的所有子视图上被调用。 …

如果在viewDidLoad中添加子视图,则在viewDidAppear之前调用layoutSubviews,并且可以获得正确大小的子视图。 但是如果你什么都不做,layoutSubviews将在viewDidAppear之后被调用。 这取决于你的代码。

在viewWillAppear()

只需调用layoutIfNeeded()一次,以获得您想要的帧的视图。

如果tableView然后tableView.layoutIfNeeded()为例