Learn more about the use of UIWindow in iOS development

  • 2020-05-12 06:15:39
  • OfStack

UIWindow is a special UIView, usually there is only one UIWindow in one app.

After the iOS program is started, the first view control created is UIWindow, then the view of the controller is created, and finally the view of the controller is added to UIWindow, so the view of the controller is displayed on the screen.

An iOS program appears on the screen only because it has UIWindow. In other words, without UIWindow, no UI interface can be seen.

How to obtain UIWindow

(1) [UIApplication sharedApplication].windows opens the UIWindow list in this application, so that you can touch any UIView object in the application (the keyboard that normally pops up for text input is in a new UIWindow);

(2) [UIApplication sharedApplication].keyWindow (get the main window of the application) is used to receive the keyboard and non-touch type of message events UIWindow, and only one UIWindow is keyWindow at a time in the program;

Note: after code verification, non-keyWindow can also accept keyboard messages;

Tip: if the text box inside an UIWindow cannot enter text, it may be because the UIWindow is not keyWindow.

(3) view.window gets UIWindow where an UIView is located.

UIWindowLevel

We know that UIWindow has three levels: Normal,StatusBar and Alert. When we output the values of the three levels, we find that the order from left to right is 0,1000,2000. In other words, Normal is the lowest level, StatusBar is the intermediate level, and Alert is the highest level. Generally, the interface of our program is at the level of Normal, and the status bar at the top of the system should be at the level of StatusBar, UIActionSheet and UIAlertView, which are usually used to interrupt the normal process and remind the user, so it is at the level of Alert.

According to the principle of window display level priority, the high level will be displayed at the top, the low level at the bottom, and the view normally displayed by our program will be at the bottom.

keyWindow

"The key window is the is designated to receive keyboard non touch related events Only one at time may time time may be the key window." this means that keyWindow is designated to receive keyboard and non-touch messages, and only one window is keyWindow at a time.

Looking at the UIWindow documentation, we can see that there are four notifications of changes to window:

UIWindowDidBecomeVisibleNotification

UIWindowDidBecomeHiddenNotification

UIWindowDidBecomeKeyNotification

UIWindowDidResignKeyNotification

The object of these four notification objects all represent the window object that is currently displayed (hidden) and has become keyWindow (not keyWindow), where userInfo is empty. So we can register these 4 messages, and then print the information to observe the changes of keyWindow and the changes of window's display and hidden

Here's how you get to keywindow

1. The default window is displayed first

2. The default window becomes keywindow

3.AlertView window is displayed

4. The default window becomes keywindow

5. Finally, window of AlertView becomes keywindow

iOS8 changes the bounds of UIWindow (Window itself rotates)

iOS 7 Window bounds before will not change as the direction, but by the iOS after 8, as the equipment in the direction of rotation, window. bounds. size. width and window bounds. size. height will change accordingly.

Do a very simple test, the code is as follows:


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
   
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(orientationChanged:)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:nil];
   
    return YES;
} - (void)orientationChanged:(NSNotification*)noti {
   
    UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
    NSString *orientationDes = nil;
    switch (orientation) {
        case UIDeviceOrientationLandscapeLeft:
            orientationDes = @"UIInterfaceOrientationLandscapeRight";
            break;
        case UIDeviceOrientationLandscapeRight:
            orientationDes = @"UIInterfaceOrientationLandscapeLeft";
            break;
        case UIDeviceOrientationPortrait:
            orientationDes = @"UIInterfaceOrientationPortrait";
            break;
        case UIDeviceOrientationPortraitUpsideDown:
            orientationDes = @"UIInterfaceOrientationPortraitUpsideDown";
            break;
        default:
            orientationDes = @"";
            break;
    }
   
    NSLog(@"system ver: %@, \rorientaion: %@, \rwindow bounds: %@",
          [UIDevice currentDevice].systemVersion,
          orientationDes,
          NSStringFromCGRect(self.window.bounds));
}


The sample code is simple: create a new project and then add the above code directly to delegate.

The result of operation on iOS 8 is as follows:


2014-06-04 09:26:32.016 SviOS8[4143:61114] system ver: 8.0, orientaion: UIInterfaceOrientationLandscapeRight, window bounds: {{0, 0}, {320, 480}} 2014-06-04 09:26:34.788 SviOS8[4143:61114] system ver: 8.0, orientaion: UIInterfaceOrientationPortrait, window bounds: {{0, 0}, {480, 320}} 2014-06-04 09:26:35.791 SviOS8[4143:61114] system ver: 8.0, orientaion: UIInterfaceOrientationLandscapeLeft, window bounds: {{0, 0}, {320, 480}} 2014-06-04 09:26:47.468 SviOS8[4143:61114] system ver: 8.0, orientaion: UIInterfaceOrientationPortraitUpsideDown, window bounds: {{0, 0}, {480, 320}}


The results of iOS 7 and previous versions are:

2014-06-04 09:39:00.527 SviOS8[4380:70b] system ver: 7.0.3,
orientaion: UIInterfaceOrientationLandscapeRight,
window bounds: {{0, 0}, {320, 480}}
2014-06-04 09:39:00.895 SviOS8[4380:70b] system ver: 7.0.3,
orientaion: UIInterfaceOrientationPortrait,
window bounds: {{0, 0}, {320, 480}}
2014-06-04 09:39:01.225 SviOS8[4380:70b] system ver: 7.0.3,
orientaion: UIInterfaceOrientationLandscapeLeft,
window bounds: {{0, 0}, {320, 480}}
2014-06-04 09:39:11.004 SviOS8[4380:70b] system ver: 7.0.3,
orientaion: UIInterfaceOrientationPortraitUpsideDown,
window bounds: {{0, 0}, {320, 480}} 


By comparison, we can clearly see that UIWindow in iOS 8 has changed its strategy when dealing with rotation. Although bug in the existing project layout will be different from the previous version, we can see that the processing mode in iOS 8 is more in line with our expectations, and we can get width in portrait < height, width in the horizontal > height, this is consistent with what you see is what you get.

As an aside, all ViewController's bounds is correct, whether it is iOS 7 or the previous version, or the latest version of iOS 8, so stick to one principle: "all layouts are based on VC.view.bounds, and your App display will be fine."


Related articles: