43

我想知道是否有人知道为什么当您设置子视图的框架viewDidLoad并且viewWillAppear更改不会对屏幕产生影响时,但是如果您将其设置在其中,viewDidAppear他们会这样做吗?

在我的情况下,我正在加载一个带有两个表视图的自定义 xib,然后尝试将它们向下移动,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;
}
4

3 回答 3

100

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

viewDidLoad - 在控制器的视图加载到内存后调用

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

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

同样,该视图尚未添加到视图层次结构中。

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

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

更新

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

viewDidLayoutSubviews - 通知视图控制器它的视图刚刚布置了它的子视图。

于 2012-10-26T00:44:15.737 回答
2

请参阅此线程何时调用 layoutSubviews?
使用自动布局时,框架不会自动调用 layoutSubviews。这是非常重要的。来自参考:

  • init 不会导致 layoutSubviews 被调用(duh)
  • addSubview:导致 layoutSubviews 在被添加的视图、它被添加到的视图(目标视图)以及目标的所有子视图上被调用。...


如果在 viewDidLoad 中添加 subview,layoutSubviews 在 vi​​ewDidAppear 之前调用,就可以得到正确的 subview 大小。但是如果你什么都不做,layoutSubviews 会在 viewDidAppear 之后被调用。这取决于你的代码。

于 2015-08-03T00:40:26.977 回答
0

在 viewWillAppear()

只需为要获取其框架的视图调用一次 layoutIfNeeded() 。

if tableView then tableView.layoutIfNeeded() 例如

于 2017-03-02T10:05:26.073 回答