关于ios:查看身高问题(续)

View height problems (continued)

这是我在这里遇到的问题(仍然没有解决)的延续:链接

但这可能有助于理解问题所在。我只创建了一个简单的测试项目("空应用程序"),并添加了一个带有XIB文件的视图控制器(选中复选框:"带有用于用户界面的XIB文件")。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"didLoad: %@",NSStringFromCGRect(self.view.bounds));

    // Do any additional setup after loading the view from its nib.
}

-(void) viewDidAppear:(BOOL)animated
{
    NSLog(@"didAppear: %@",NSStringFromCGRect(self.view.bounds));

}

这是输出:

1
2
2013-07-26 17:05:28.502 testtest[5926:c07] didLoad: {{0, 0}, {320, 548}}
2013-07-26 17:05:28.506 testtest[5926:c07] didAppear: {{0, 0}, {320, 460}}

他们为什么不一样?

(我正在6.1模拟器上测试)


当调用viewDidLoad方法时,视图控制器只是从故事板或xib中加载的,因此视图尺寸等于xib中的视图尺寸(类似于iPhone5高度尺寸)。

稍后,当调用viewDidAppear:时,视图已经出现在屏幕上,因此它已经适当地调整了大小以实际适合屏幕,因此它的尺寸可能与故事板中的尺寸不同,因此与加载视图时设置的尺寸不同。

在您的情况下,您的故事板或XIB文件似乎被设置为iPhone 5屏幕大小(548=1136/2-状态栏),并且您正在使用480x320点屏幕的iPhone 5之前的模拟器或设备中进行测试,因此视图的大小被调整到460点高以适应屏幕。


这可能有完美的感觉。

当第一次访问controller.view时,viewDidLoad被称为lazy,所以到那时帧还没有设置。这意味着此时不能依赖帧/边界大小,因为它只包含默认值(尽管在许多情况下它是正确的)。在viewDidAppear中,通常会设置帧,但如果父控制器正在设置任何动画,则也可以使用临时帧状态而不是最终帧状态,但这与惯例不同,当视图已显示时调用此方法。

例如,如果您从一个ib文件加载视图,那么您将在viewDidLoad中得到的帧就是您在ib文件中得到的帧,但是您的视图的最终大小可能更小/更大,然后您将在viewDidAppear中得到另一个帧。

相反,您应该创建所有可调整大小的元素(使用spring&struts、autolayout或任何其他类似选项),以便在设置框架时正确显示这些元素。


第一次调用viewController.view,就称为-viewDidLoad。在返回视图之前调用它。这有一个非常重要的含义。为了显示或调整视图的大小,需要将其添加到窗口或其他视图中。

这是怎么发生的?它看起来像[window addSubview:viewController.view]

因此,在将完全加载的视图放入视图层次结构之前,需要它。这就限制了在-viewDidLoad中使用self.view

  • self.view.superviewself.view.window永远是nil
  • self.view的尺寸还不适合self.view.superview的尺寸。
  • 通过这种理解,您可以看到当调用-viewDidLoad时,self.view是如何不知道它的最终大小的。

    更新

    如果需要将自定义布局应用于视图的子视图,则可以考虑子类化UIView和使用-[UIView layoutSubviews]

    除此之外,你在使用-viewWillAppear:而不是-viewDidAppear:时有问题吗?在显示视图之前调用-viewWillAppear:,因此在调整视图大小时不会产生奇怪的视觉效果。


    据我所知,viewdidload将为您的应用程序设置定义的界限,在rootviewcontroller/xib文件中为根视图,或者可能是appdelegate。

    如果您定义了应用程序的边界(不确定其中的哪一个),整个应用程序中的viewdidload函数将首先根据该边界设置高度。

    加载视图并准备好"显示"后,可以请求实际边界。因此,建议在viewwillappear/viewdidappear方法中请求边界/大小。


    When a ViewController presents its view, it normally shrinks that
    view so that its frame does not overlap the device’s status bar.

    所以当你在viewDidLoad中使用NSLog时,我还没有加载的视图,所以ViewController还没有缩小框架,但是在viewDidAppear中,它已经进行了调整。UIViewController有一处房产wantsFullScreenLayout

    Setting this property to YES causes the view controller to size its
    view so that it fills the entire screen, including the area under the
    status bar. (Of course, for this to happen, the window hosting the
    view controller must itself be sized to fill the entire screen,
    including the area underneath the status bar.) You would typically set
    this property to YES in cases where you have a translucent status bar
    and want your view’s content to be visible behind that view.