Multiple UIWindows

Guides | Tutorial By 5 years ago

When you need to display a view or view controller over every other element in an iOS application, most people go ahead and add it directly to the main window. This may work but can require a bit of tweaking in order to implement your own rotation code if you want to support more than one orientation, and could be later overlaid by things that are supposed to remain behind.

Instead of adding it directly to your existing UIWindow, a better solution is to create a new UIWindow on top of the existing one and then adding things to this UIWindow. It’s recommended to add a UIViewController to this window so all rotations are handled for you.

Doing this is quite easy, although will be foreign to most people as new projects are set up with an initial UIWindow for you and generally don’t need to be looked at ever again.

UIWindow* topWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[topWindow setWindowLevel:UIWindowLevelNormal];
[topWindow setBackgroundColor:[UIColor greenColor]];

[topWindow makeKeyAndVisible];

The first line creates the window, the same size as the screen. The next line works like a Z position. There are three standard levels a window can sit on: UIWindowLevelNormal, UIWindowLevelAlert and UIWindowLevelStatusBar. The UIWindow subclasses a UIView, so you can do the same things you could on a view, but with added bonuses of being a window. Finally the window is made ‘key and visible’, meaning it becomes the key window and hidden is set to NO. The same thing could be done in two lines.

[topWindow makeKeyWindow];
[topWindow setHidden:NO];

And then you can do some fancy stuff (code below):

UIWindow* topWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[topWindow setWindowLevel:UIWindowLevelAlert];

CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;

UIViewController* viewController = [[ViewController alloc] init];
UIView* overlay = [[UIView alloc] initWithFrame:CGRectMake(0, -statusBarHeight, viewController.view.frame.size.width, statusBarHeight - 1)];
[overlay setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[overlay setBackgroundColor:[UIColor colorWithRed:1 green:0 blue:0 alpha:0.5]];
[viewController.view addSubview:overlay];
[topWindow setRootViewController:viewController];

[topWindow setHidden:NO];
[topWindow setUserInteractionEnabled:NO];

[viewController release];
viewController = nil;

[overlay release];
overlay = nil;
  • Andrei Shender

    Hi! Nice post. Is there any possibility to lock orientation of all windows from the key one. The thing I want to implement is library with UI and I need modal on Iphone with transparency locked in portrait. thanx

    • Tom

      The UIWindow doesn’t have a concept of orientation, but instead the UIViewController inside the UIWindow will rotate based on it’s supported orientations. If you want to allow or disallow certain orientations, start with the root UIViewController inside the UIWindow.

      • Andrei Shender

        Yes, I can do it for one window using root or modal controller in that window. What about ALL windows, without ability to subclass UIApplication.

        • Tom

          I’d recommend you set a root view controller for all your UIWindows that you create, and then put the rotation logic in each of those view controllers