首页 > 技术文章 > UIwindow的学习

pocket-mood 2015-05-05 18:39 原文

UIwindow 的学习

 

层级关系测试代码:

 

@interface AppDelegate ()

@property (nonatomic, strong) UIWindow *arlewWindow;
@property (nonatomic, strong) UIWindow *norWindow;
@property (nonatomic, strong) UIWindow *statusWindow;

@end

 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // UIStoryboard中没有设置了程序入口箭头
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor greenColor];
    UIStoryboard *story = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    UIViewController *oneView = [story instantiateViewControllerWithIdentifier:@"123"];
    self.window.rootViewController = oneView;
    NSLog(@"%f",self.window.windowLevel);
    [self.window makeKeyAndVisible];
    
    // 最低级别
    UIWindow *norWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 520)];
    self.norWindow = norWindow;
    norWindow.windowLevel = UIWindowLevelNormal + 1;
    norWindow.backgroundColor = [UIColor redColor];
    NSLog(@"norWindow.windowLevel:%f",norWindow.windowLevel);
    [norWindow makeKeyAndVisible];
    
    // 中等级别
    UIWindow *statusWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 50, 100, 100)];
    self.statusWindow = statusWindow;
    statusWindow.windowLevel = UIWindowLevelStatusBar;
    statusWindow.backgroundColor = [UIColor grayColor];
    NSLog(@"statusWindow.windowLevel:%f",statusWindow.windowLevel);
    [statusWindow makeKeyAndVisible];
    
    // 最高级别
    UIWindow *arlewWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 100, 320, 30)];
    self.arlewWindow = arlewWindow;
    arlewWindow.windowLevel = UIWindowLevelAlert;
    arlewWindow.backgroundColor = [UIColor yellowColor];
    NSLog(@"arlewWindow.windowLevel:%f",arlewWindow.windowLevel);
    [arlewWindow makeKeyAndVisible];
    
    // 经过总结,self.window.windowLevel默认是UIWindowLevelNormal,window按照层级级别来显示,不管谁先谁后makeKeyAndVisible,层级最高的总是显示在前面,如果是相同层级的window,按照显示顺序是按照 [_window makeKeyAndVisible];的顺序显示,最后makeKeyAndVisible的window显示在最前面。小技巧:如果想要设置不大不小的层级级别,可以norWindow.windowLevel = UIWindowLevelNormal + 1;来增加级别权限。
    // 如果是非ARC模式测验则没问题,但是在ARC模式下测验则会不显示其他window,只会显示self.window,因为其他的window没有strong进行引用,没有人持有,会被释放掉,如果想在ARC下测试,则要将window定义为类的属性
    
    
    return YES;
}

 

// 通过遍历以及打印信息提取自己想要的app中得window
for (UIWindow *window in [UIApplication sharedApplication].windows) {
        NSLog(@"window:%@, %f",window, window.windowLevel);
        
        
    }
    // 取出self.window
    UIWindow *window = [[UIApplication sharedApplication].windows objectAtIndex:2];
    // 增加self.window的层级权限
    window.windowLevel = UIWindowLevelNormal + 30;

 

 

如果你的window在某个类中做为属性创建,并且使用完后保证没有其他地方strong引用window的话,那么这个类释放的时候,window属性自然就释放了。

 

[UIApplication sharedApplication].windows  // 在本应用中打开的UIWindow列表

[UIApplication sharedApplication].keyWindow  //(获取应用程序的主窗口)

//UIScreen屏幕属性

@property(nonatomic,retain) UIScreen *screen

 

keyWindow

 官方解释keyWindow是唯一一个可以接受响应的Window,在一个应用程序中只有唯一一个keyWindow

    但是iOS7.0检验发现非keyWindow也是可以接受键盘消息,这一点和文档上说的不太一样。

 

层级

// UIWindowLevel属性(层级高度)

@property(nonatomic) UIWindowLevel windowLevel; 

// 定义UIWindow展示优先级不同层次的选择 ,根据window显示级别优先的原则,级别高的灰显示在上面,级别低的在下面,我们程序正常显示的位于最底层

UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal; //默认的window就是Normal级别,优先级值这个层次的值为0,通常我们程序的界面都是处于这个Normal级别的

UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert; //屏幕的statusBar处于中等水平,优先级值为1000

UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar;// alert级别的,通常是UIAlertView和UIAlertSheet这些用来中断正常流程,提醒用户等操作的。优先级值为2000.按照这样说来,alertView弹框出来下面也是一层UIWindow,只不过是优先级最高的alert级别,所以是keyWindow,当前只能交互alert,这就是为什么弹框出来其他界面都不可交互的原因 (UIAlertView为1996,UIAlertSheet为2001)

 

方法

 

- (void)becomeKeyWindow; // 调用窗口,使之变成关键窗口(设置当前window变成主window

- (void)resignKeyWindow;  //  调用窗口,使之取消关键窗口(设置当前window变成主window

- (void)makeKeyWindow;     // 使之成为主窗口(让当前window变成keyWindow)

- (void)makeKeyAndVisible;  // 使之成为主窗口,并且显示(让当前window变成keyWindow,并显示出来

 

类的属性

 

@property(nonatomic,retain) UIViewController *rootViewController // 根控制器(设置UIViewController为根控制器

 

// 当产生一个事件时,先传递给UIApplication,而UIAppliaction将这个事件传递UIWindow进行处理,然后由UIWindow将这个时间传递给特定的对象,即first responder,而UIWindow就是通过sendEvent寻找first responder,经过sendEvent分发到合适的对象,sendEvent就相当于时间的中转站。

- (void)sendEvent:(UIEvent *)event;

 

通知

 

// window变化的四个通知

UIKIT_EXTERN NSString *const UIWindowDidBecomeVisibleNotification; //当window显示就会调用

UIKIT_EXTERN NSString *const UIWindowDidBecomeHiddenNotification;  //window被隐藏之后调用,需要注意的是,当程序进入后台时,这两个通知不会被调用,即使应用转到后台,窗口不会显示,窗口应用下的上下文中仍然被认为是可见的

UIKIT_EXTERN NSString *const UIWindowDidBecomeKeyNotification;     //window成为主窗口调用

UIKIT_EXTERN NSString *const UIWindowDidResignKeyNotification;     //window撤销主窗口调用

 

// 监听键盘变化的通知

UIKIT_EXTERN NSString *const UIKeyboardWillShowNotification; //当键盘将要显示的时候调用

UIKIT_EXTERN NSString *const UIKeyboardDidShowNotification; //当键盘已经显示的时候调用

UIKIT_EXTERN NSString *const UIKeyboardWillHideNotification; //当键盘将要隐藏的时候调用

UIKIT_EXTERN NSString *const UIKeyboardDidHideNotification; //当键盘隐藏完毕的时候调用

 

// 关于监听键盘通知的一些userInfo消息

UIKIT_EXTERN NSString *const UIKeyboardFrameBeginUserInfoKey       NS_AVAILABLE_IOS(3_2); //动画前键盘的位置,包含CGRectNSValue 可以在通知方法中写得到位置

CGRect rect = [[notif.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

UIKIT_EXTERN NSString *const UIKeyboardFrameEndUserInfoKey         NS_AVAILABLE_IOS(3_2); //动画结束后键盘的位置  包含CGRectNSValue

UIKIT_EXTERN NSString *const UIKeyboardAnimationDurationUserInfoKeyNS_AVAILABLE_IOS(3_0); //动画的持续时间,数值是NSNumber

UIKIT_EXTERN NSString *const UIKeyboardAnimationCurveUserInfoKey   NS_AVAILABLE_IOS(3_0); //动画的曲线类型(UIViewAnimationCurve),数值是NSNumber

 

// 监听键盘frame大小变化的通知

UIKIT_EXTERN NSString *const UIKeyboardWillChangeFrameNotification NS_AVAILABLE_IOS(5_0); //当键盘frame值将要改变的时候调用

UIKIT_EXTERN NSString *const UIKeyboardDidChangeFrameNotification  NS_AVAILABLE_IOS(5_0); //当键盘frame值已经改变的时候调用

推荐阅读