UIViewController返回无效帧?

ary*_*axt 38 landscape uiviewcontroller ios

当我在landscape模式下启动我的ViewController时(在调用viewDidLoad之后),我打印框架,它给了我纵向模式的帧大小.

这是一个bug有什么建议吗?

- (void)viewDidLoad
{
   [super viewDidLoad];

   NSLog(@"%@", NSStringFromCGRect(self.view.frame));
   // Result is (0, 0 , 768, 1024)
}
Run Code Online (Sandbox Code Playgroud)

rob*_*off 158

有几件事你不明白.

首先,系统viewDidLoad在加载你的笔尖后立即发送给你.它甚至没有将视图添加到视图层次结构中.因此,它还没有根据设备的轮换调整视图大小.

其次,视图的框架位于其超视图的坐标空间中.如果这是您的根视图,则其超级视图将是UIWindow(一旦系统实际将视图添加到视图层次结构中).将UIWindow通过设置手柄转动变换其子视图.这意味着视图的框架不一定是您所期望的.

这是纵向的视图层次结构:

(lldb) po [[UIApp keyWindow] recursiveDescription]
(id) $1 = 0x09532dc0 <UIWindow: 0x9632900; frame = (0 0; 768 1024); layer = <UIWindowLayer: 0x96329f0>>
   | <UIView: 0x9634ee0; frame = (0 20; 768 1004); autoresize = W+H; layer = <CALayer: 0x9633b50>>
Run Code Online (Sandbox Code Playgroud)

这是横向左方向的视图层次结构:

(lldb) po [[UIApp keyWindow] recursiveDescription]
(id) $2 = 0x09635e70 <UIWindow: 0x9632900; frame = (0 0; 768 1024); layer = <UIWindowLayer: 0x96329f0>>
   | <UIView: 0x9634ee0; frame = (20 0; 748 1024); transform = [0, -1, 1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x9633b50>>
Run Code Online (Sandbox Code Playgroud)

请注意,在横向方向上,帧大小为748 x 1024,而不是 1024 x 748.

你可能想看的是,如果这是你的根视图,那就是视图的界限:

(lldb) p (CGRect)[0x9634ee0 bounds]
(CGRect) $3 = {
  (CGPoint) origin = {
    (CGFloat) x = 0
    (CGFloat) y = 0
  }
  (CGSize) size = {
    (CGFloat) width = 1024
    (CGFloat) height = 748
  }
}
Run Code Online (Sandbox Code Playgroud)

据推测,您想知道视图的变换,框架和边界何时更新.如果视图控制器加载其视图时界面处于横向,您将按以下顺序接收消息:

{{0, 0}, {768, 1004}} viewDidLoad
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation:
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation:
{{0, 0}, {768, 1004}} viewWillAppear:
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation:
{{0, 0}, {768, 1004}} shouldAutorotateToInterfaceOrientation:
{{0, 0}, {768, 1004}} willRotateToInterfaceOrientation:duration:
{{0, 0}, {1024, 748}} viewWillLayoutSubviews
{{0, 0}, {1024, 748}} layoutSubviews
{{0, 0}, {1024, 748}} viewDidLayoutSubviews
{{0, 0}, {1024, 748}} willAnimateRotationToInterfaceOrientation:duration:
{{0, 0}, {1024, 748}} shouldAutorotateToInterfaceOrientation:
{{0, 0}, {1024, 748}} viewDidAppear:
Run Code Online (Sandbox Code Playgroud)

你可以看到你的视图边界改变,你收到willRotateToInterfaceOrientation:duration:之前收到viewWillLayoutSubviews.

这些viewWillLayoutSubviewsviewDidLayoutSubviews方法是iOS 5.0的新增功能.

layoutSubviews消息被发送到视图,不视图控制器,所以你需要创建一个自定义的UIView子类,如果你想使用它.