UIWindow addSubview上的偏移量

时间:2010-02-11 20:55:58

标签: iphone cocoa-touch

我有一个基于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显示得很好。

我有点困惑,这里没有想法。有任何建议如何跟踪这个?

4 个答案:

答案 0 :(得分:76)

将根视图添加到UIWindow可能很复杂,因为窗口始终是状态栏的下层。因此,必须将根视图的框架重置为[[UIScreen mainScreen] applicationFrame],以防止其覆盖状态栏。我们通常不必担心这个,因为UIViewController会为我们修改框架...除非它没有。这是交易:

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

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

答案 1 :(得分:4)

这更简单,也适用(iOS 4.0及更高版本)

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

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

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

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

答案 2 :(得分:0)

我假设您的UITabBarController是IB出口,因此当调用applicationDidFinishLaunching:时,它已经初始化。请尝试以下操作:在实例化视图控制器后,执行:

[vc setWantsFullScreenLayout:YES];

答案 3 :(得分:0)

刚才上面说的是:这是我必须使用的代码:

#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];

  // ...
}