Iphone 为什么我必须手动设置视图';viewDidLoad中的s帧?

Iphone 为什么我必须手动设置视图';viewDidLoad中的s帧?,iphone,ipad,uiview,frame,viewdidload,Iphone,Ipad,Uiview,Frame,Viewdidload,我有一个非常基本的设置,在UIDABBARC控制器中有一个UINavigationController。我想以编程方式布局该navcontroller的rootViewController的视图,但当我查看viewDidLoad中的self.view.frame时,我得到了以下结果(例如,在横向中): 然后我自动旋转到肖像,我得到: 2. view frame: {{0, 0}, {768, 911}} 然后,当我回到景观时,画面是这样的: 3. view frame: {{0, 0}, {1

我有一个非常基本的设置,在UIDABBARC控制器中有一个UINavigationController。我想以编程方式布局该navcontroller的rootViewController的视图,但当我查看viewDidLoad中的self.view.frame时,我得到了以下结果(例如,在横向中):

然后我自动旋转到肖像,我得到:

2. view frame: {{0, 0}, {768, 911}}
然后,当我回到景观时,画面是这样的:

3. view frame: {{0, 0}, {1024, 655}}
进一步的自动旋转事件将在帧值#2和#3之间切换

为了避免#1的奇怪之处,我目前正在viewDidLoad中执行以下操作:

if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
    self.view.frame = CGRectMake(0, 0, 768, 911);
} else {
    self.view.frame = CGRectMake(0, 0, 1024, 655);
}
我觉得我显然错过了一些东西。为什么视图的默认帧在自动旋转回同一方向时与帧不匹配?图幅是否未设置为初始方向?非常困惑

我应该提到的是,上述任何一项,包括我的拙劣的黑客,都不会在视觉上改变任何东西。我这样做的原因是,当我在这个视图中布局我的子视图时,它们将基于我预期的位置,即导航栏下的左上角

我做错了什么

更新:关闭视图上的所有自动大小调整功能会将结果#1更改为:


这似乎有点接近,但仍然不匹配#3。

您的类中将有一个方法

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations    return YES; }
把你的框架放在这个方法里。。。那它就可以正常工作了

例如:

1. view frame: {{20, 0}, {748, 1024}} // looks like an odd portrait mode
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{
        // Return YES for supported orientations    
        if(interfaceOrientation == UIDeviceOrientationPortrait || UIDeviceOrientationPortraitUpsideDown)
                self.view.frame = CGRectMake(0, 0, FRAME.WIDTHinPOTRAIT, FRAME.HEIGHTinPOTRAIT);
        else if(interfaceOrientation == UIDeviceOrientationLandscapeRight || UIDeviceOrientationLandscapeLeft)
                self.view.frame = CGRectMake(0, 0, FRAME.WIDTHinLANDSCAPE, FRAME.HEIGHTinLANDSCAPE);

        return YES; 
}
FRAME.WIDTH>所需宽度
FRAME.HEIGHT>所需高度

不能保证viewDidLoad中的帧与最终显示视图时的帧相同。UIKit在显示视图控制器的视图之前,根据显示的上下文调整视图控制器视图的框架。大小取决于界面方向和任何可见导航栏、选项卡栏、工具栏或状态栏的尺寸(其本身的高度可以更改,例如在通话时)

它有助于理解在加载和显示视图控制器的视图时会发生什么:

  • 某些内容首次访问视图控制器的
    视图
    属性。这可能发生在您自己的代码中,也可能发生在UIKit中,以响应用户的操作,如选择选项卡

  • UIKit lazy通过调用
    loadView
    加载视图控制器的视图(如果已定义),或者通过从
    initWithNibName:bundle:
    中指定的NIB加载视图来加载视图控制器的视图。如果两者都不存在,UIKit只加载一个空视图

  • 视图及其子视图完全加载后,UIKit调用
    viewDidLoad
    此时,视图的帧将是NIB中或
    加载视图中设置的任何帧

  • 需要UIKit显示视图控制器的视图。同样,这可能是一个用户操作,如点击选项卡,也可能是代码中的一个显式方法调用,如
    pushViewController:animated:
    presentModalViewController:animated:

  • 如上所述,UIKit根据视图显示的上下文调整视图大小

  • UIKit调用
    视图将出现:
    框架现在应为将显示的大小。(?)编辑:这可能不再正确。见下面的评论

  • UIKit显示视图,包括或不包括动画

  • UIKit调用
    viewdide:

  • 如您所见,如果您需要在视图显示之前了解其框架的大小,
    viewwillbeen:
    是您唯一的机会。请记住,在视图出现后,由于各种原因,包括旋转事件或状态栏高度的更改,此大小可能会更改。因此,为每个子视图提供一个适当的autoresizingMask非常重要,以确保布局能够针对边界的任何更改进行适当的调整


    如果希望手动构建视图层次结构,建议在loadView中执行此操作。由于您自己使用此方法构造视图,因此可以将其框架初始化为您想要的任何内容。你选择的尺寸无关紧要,因为UIKit很可能会改变你的尺寸。只需确保您正确设置了自动重新设定屏幕即可。

    关于您的答案3,我有一个问题。我曾尝试在nib文件中设置视图,但在viewDidLoad中,我的视图框不是在nib中设置的。奇怪的是,我在这里发布了我的问题,我的视图直到第8步才有正确的框架
    viewdide出现:
    frame在iOS 5.0+@MrRogers的
    viewdidelayoutsubviews中可用。ViewDidDisplay中不保证帧大小/位置:。使用自动布局时,应使用viewDidLayoutSubviews而不是ViewWillDisplay。这看起来也很有用:在
    shouldAutorotate
    中调整
    self.view
    的大小正是UIKit文档所说的不应该做的。
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
    {
            // Return YES for supported orientations    
            if(interfaceOrientation == UIDeviceOrientationPortrait || UIDeviceOrientationPortraitUpsideDown)
                    self.view.frame = CGRectMake(0, 0, FRAME.WIDTHinPOTRAIT, FRAME.HEIGHTinPOTRAIT);
            else if(interfaceOrientation == UIDeviceOrientationLandscapeRight || UIDeviceOrientationLandscapeLeft)
                    self.view.frame = CGRectMake(0, 0, FRAME.WIDTHinLANDSCAPE, FRAME.HEIGHTinLANDSCAPE);
    
            return YES; 
    }