应用程序变为活动状态后,UIWindow子视图消失

时间:2012-05-03 14:27:23

标签: iphone ios uiview uiviewcontroller

所以,我试图在Application UIWindow上实现固定的顶部横幅和多个视图控制器的工作导航。我知道还有其他方法可以执行此操作,但对于我的项目要求,我需要使用xibs。

以下代码可以实现此目的:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    self.headerView = [[UIImageView alloc] init];
    self.headerView.frame = CGRectMake(0.0f, 20.0f, 320.0f, 44.0f);
    self.headerView.image = [UIImage imageNamed: @"header-banner-background.png"];
    [self.window addSubview:self.headerView];

    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];

    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];

    self.window.rootViewController = navigationController;
    [self.window makeKeyAndVisible];
    return YES;
}

然后在每个ViewController viewWillAppear方法中,我调整了self.view和self.navigationController.navigationBar.frame的大小,以便在横幅下方显示自己:

self.navigationController.navigationBar.frame = CGRectMake(0, 64, 320, 44);
self.view.frame = CGRectMake(0, 64, 320, 396); 

这很好,完全按我想要的方式工作。

但是如果用户按下主页按钮并且应用程序处于活动状态,则当它再次变为活动状态时,最后一个看到的viewController会显示但没有UIWindow横幅,并且self.view和navigationBar显示在顶部。 / strong>

当然,当应用程序返回活动状态时,不会调用当前的UIViewController viewWillAppear方法,但即使我将调整大小代码放在另一个函数中并通过通知调用它也不起作用。但是当用户按下一个条形项并在导航堆栈中移动时,一切都会再次起作用,UIWindow会显示headerView。

任何人都明白为什么当应用程序返回活动状态时UIWindow headerView会消失?

编辑1:可能的解决方案?

@interface RootViewController ()
{
    ViewController *viewController;
    UINavigationController *navigationController;
}

@end

@implementation RootViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
        navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
    }
    return self;
}

- (void)loadView
{
    // Implement loadView to create a view hierarchy programmatically, without using a nib.
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 88)];

    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    [imageView setImage:[UIImage imageNamed:@"header"]];

    [view addSubview:imageView];

    navigationController.navigationBar.frame = CGRectMake(0, 44, 320, 44); 

    [view addSubview:navigationController.navigationBar];

    self.view = view;

}

编辑2:第二种可能的解决方案,仍无法正常工作

- (void)loadView
{
    NSLog(@"loadView root");

    // Implement loadView to create a view hierarchy programmatically, without using a nib.
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 88)];

    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    [imageView setImage:[UIImage imageNamed:@"banner"]];
    [view addSubview:imageView];

    navigationController = [[UINavigationController alloc] init];
    navigationController.navigationBar.frame = CGRectMake(0, 43, 320, 44); 
    [view addSubview:navigationController.navigationBar];

    [self addChildViewController:navigationController];

    self.view = view;
    [self.view setBackgroundColor:[UIColor yellowColor]];
}

这是结果,看起来不错,没有按下viewController1(注意黄色背景来自rootViewController):

Without push

这是添加:

的结果
- (void)viewDidLoad
{
    viewController1 = [[ViewController1 alloc] initWithNibName:@"ViewController1" bundle:nil];
    [navigationController pushViewController:viewController1 animated:YES];    
}

With PUSH

未按下新的视图控制器(背景应为黑色),导航栏已消失。

编辑3:Olloqui解决方案,仍无法正常工作

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self.window setBackgroundColor:[UIColor redColor]];

  UIView *bannerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    [self.window addSubview:bannerView];

    UIView *navigationView = [[UIView alloc] initWithFrame:CGRectMake(0, 44, 320, 416)];

    ViewController1 *viewController1 = [[ViewController1 alloc] initWithNibName:@"ViewController1" bundle:nil];
    self.navigationController = [[UINavigationController alloc] initWithRootViewController:viewController1];
    self.navigationController.navigationBar.frame = CGRectMake(0, 0, 320, 44); 

    [navigationView addSubview:self.navigationController.navigationBar];

    [self.window addSubview:navigationView];

    self.window.rootViewController = self.navigationController;

    self.window.autoresizesSubviews = YES;

    [self.window makeKeyAndVisible];
    return YES;
}

结果是我只有横幅,按下了viewController1,但没有显示导航栏。我真的需要弄清楚这一点,任何人都有不同的方法吗?

4 个答案:

答案 0 :(得分:1)

窗口期望具有由其rootViewController属性控制的根视图。从后台返回时,窗口仅要求rootViewController恢复该视图控制器视图的外观。它不会要求所有子视图刷新。

要解决这个问题,我会创建一个新的根视图控制器。这将有横幅和导航控制器。然后,该导航控制器将保持您的普通视图控制器并管理导航。当应用程序从后台返回时,横幅将正确显示。导航控制器中导航时,您的横幅将静止不动。

编辑:我掀起了一个示例程序。

我从一个简单的单一视图应用模板开始。我为内容添加了两个视图控制器。只是有区分标签,一个有一个加载第二个视图的按钮。

所有魔法都发生在主视图控制器的viewDidLoad方法中:

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    OneViewController *oneVC = [[OneViewController alloc] initWithNibName:@"OneViewController" bundle:nil];
    self.navController = [[UINavigationController alloc]initWithRootViewController:oneVC];
    self.navController.view.frame = CGRectMake(0.0, 64.0, 320.0, 416.0);
    [self.view addSubview:self.navController.view];
    [self addChildViewController:self.navController];   
}

此视图的笔尖加载横幅的图像视图。

The example project in on Bitbucket.

答案 1 :(得分:1)

我之前从未尝试过,但我会在UIWindow中创建2个视图,一个用于横幅,另一个用于导航+内容。然后,在第二个视图中插入navigationBar视图,该视图将正确调整大小。我不确定导航是否会尝试占用整个窗口,但是在每个viewWillAppear上调整导航控制器的大小对我来说并不是一个好的解决方案。试一试并评论结果!

答案 2 :(得分:1)

我认为您可以尝试通过向window.rootViewController.view添加横幅视图来解决此问题,如下所示:

[window.rootViewController.view addSubview:bannerView]

答案 3 :(得分:0)

好的,我真的需要尽快解决这个问题,因此我选择了一个解决方案,我很幸运地找到了here。我仍然需要解决在底部添加的UITabBarController的管理,但其余的似乎工作正常。感谢大家的帮助和其他提示。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    [self.window setBackgroundColor:[UIColor redColor]];

    // Create a view  for the banner add the banner to this view
    UIImageView *bannerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 45)];
    bannerImageView.image = [UIImage imageNamed:@"banner"];

    // put this banner above the nav bar 
    UIView *bannerView = [[UIView alloc] initWithFrame:CGRectMake(0, -44, 320, 44)];
    [bannerView addSubview:bannerImageView];

    //add the tabBarController as a subview of the view
    UITabBarController *tabBarController = [[UITabBarController alloc] init];
    [tabBarController.view addSubview:bannerView];

    // Move the root view to show status bar & banner
    tabBarController.view.frame = CGRectMake(0, 20+44, 320, 480-20-44); 

    //add the modified logo view to window
    [self.window addSubview:tabBarController.view];

    ViewController1 *viewController1 = [[ViewController1 alloc] initWithNibName:@"ViewController1" bundle:nil];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController1];

    tabBarController.viewControllers = [NSArray arrayWithObjects:navigationController, nil];
    //tabBarController.tabBar.hidden = YES;

    [self.window setRootViewController:tabBarController];

    [self.window makeKeyAndVisible];
    return YES;
}