UIWindow addSubview 上的偏移量

Posted

技术标签:

【中文标题】UIWindow addSubview 上的偏移量【英文标题】:Offset on UIWindow addSubview 【发布时间】:2010-02-11 20:55:57 【问题描述】:

我有一个运行良好的基于​​ UITabBar 的应用程序。在某些情况下,我会显示不同的 UIViewController。现在让我烦恼的是,我必须调整测试笔尖的框架(并且测试笔尖!)才能正确显示。 (否则视图位于状态栏下方)。

- (void)applicationDidFinishLaunching:(UIApplication *)application

    if (condition) 

        UIViewController *vc = [[UIViewController alloc] initWithNibName:@"Test" bundle:nil];

        // FIXME this should NOT be required
        CGRect r = vc.view.frame;
        r.origin.y += 20;
        vc.view.frame = r;

        [window addSubview:vc.view];
        [window makeKeyAndVisible];
        return;
    

    [window addSubview:tabViewController.view];
    [window makeKeyAndVisible];

所以也许测试笔尖有问题?不可能。测试笔尖在一个干净的新项目中按需要工作。一个新的干净笔尖也会出现同样的症状。所以 MainWindow 笔尖一定有问题,对吧?但是 UITabBarController 显示得很好。

我有点困惑,在这里没有想法。有什么建议如何追踪吗?

【问题讨论】:

【参考方案1】:

将根视图添加到 UIWindow 可能会很复杂,因为窗口始终位于状态栏之下。因此,您的根视图的框架必须重置为[[UIScreen mainScreen] applicationFrame],以防止它也与状态栏重叠。我们通常不必担心这一点,因为 UIViewController 会为我们修改框架……除非它没有。这是交易:

如果您创建视图控制器 和它在同一个NIB中的视图,而你 将视图嵌套在视图下方 控制器,它自动调整视图的框架。 如果您创建视图控制器并 它在同一个 NIB 中的视图,但你 将视图连接到视图 控制器通过控制器的 view outlet 而不是嵌套它,控制器不会自动调整视图的框架。 如果您在一个 NIB 中创建视图控制器,并通过在 IB 中设置视图控制器的“NIB 名称”属性将其连接到在分离的 NIB 中定义的视图,它 自动调整视图的框架,但仅当您还选中了“Resize view from NIB”。 如果您通过调用 -initWithNibName:bundle: 创建视图控制器,它不会自动调整视图的框架。 UITabBarController 期望它的视图被添加为窗口的根视图,因此总是自动调整它自己的视图框架以匹配应用程序框架。 (因此,如果您将 UITabBarController 的视图添加为窗口以外的任何内容的子视图,您会注意到一个奇怪的 20 像素间隙。)

我猜 Apple 认为 -initWithNibName:bundle: 通常不会用于创建窗口的根视图,因此它不会在您的情况下调整框架。像您所做的那样手动调整它的大小很好,实际上在View Controller Programming Guide for iPhone OS 中推荐,但您应该真正使用[[UIScreen mainScreen] applicationFrame],因为状态栏不是总是 20 像素高(例如,它是打电话时更高。)

【讨论】:

ios 开发中最烦人的常见怪事之一的最终答案。 5 星,10/10,会再玩 不要完整阅读您的答案,但我对关键字 [[UIScreen mainScreen] applicationFrame] 很满意【参考方案2】:

这更简单,也可以工作(iOS 4.0 及更高版本)

MyRootViewController *vc = [[MyRootViewController alloc] init];    
[window setRootViewController:vc];
[vc release];

-setRootViewController 自动将控制器的视图添加到窗口中,因此您无需担心。该属性是(非原子的,保留),因此在将其分配给窗口后释放它有效地将对象的所有权移交给 UIWindow,并且在窗口被释放时将被释放(并因此被释放)。如果您想在其他应用程序委托方法中使用它,您当然可以创建一个实例变量并保留对它的引用并在 -dealloc 中释放。我更喜欢上述方法,因为它会自动进行清理。

如果您不知道,您也可以在将视图控制器作为子视图添加到任何其他视图或呈现模态视图控制器视图后立即释放视图控制器。每当视图被移除或从视图堆栈中弹出时,它们相应的控制器也将被释放。

您不需要使用 initWithNibName,只需 ...alloc] init];会的。

【讨论】:

【参考方案3】:

我假设你的UITabBarController 是一个IB 出口,所以当applicationDidFinishLaunching: 被调用时,它已经被初始化了。尝试以下操作:在实例化视图控制器之后,执行以下操作:

[vc setWantsFullScreenLayout:YES];

【讨论】:

在调用这个之后,屏幕底部的 20 像素(是白色而不是视图的背景颜色)消失并且整个区域都被覆盖了。但是 UI 控件仍然离顶部太近了 20 像素。所以我认为这只是将视图的大小从 320x460 调整为 320x480。出处还是错的。毕竟这也只是一种变通方法。我想找出原因。【参考方案4】:

只是为了支持上面所说的:这是我必须使用的代码:

#define MAIN_SCREEN_OFFSET_PIXELS     20

- (void) pushDownViewOnMainScreen 
  CGRect r = [[UIScreen mainScreen] applicationFrame];
  r.origin.y -= MAIN_SCREEN_OFFSET_PIXELS;

  self.view.frame = r;



- (void) viewDidLoad 
  [self pushDownViewOnMainScreen];

  // ...

【讨论】:

以上是关于UIWindow addSubview 上的偏移量的主要内容,如果未能解决你的问题,请参考以下文章

UIWindow 在 addSubview 之后不更新子视图

UIWindow 和 UIView addSubview 问题

UIWindow addSubview 处理事件

将视图控制器添加到 uiwindow addsubview

Objective-C中的rootViewController和addSubview?

UIButton 在 UIWindow 的子视图上不起作用