UIWindow的windowLevel属性

UIWindow是我们必不可少的类,可能使用的较少,但是一个项目中少它不行,因为它是我们最顶层的界面容器,我们自己的相关的ViewController都要最终放到window.rootController中。一班情况UIWindow作为顶层容器的存在。
介绍下UIWindow的一个属性,windowLevel。
苹果文档中windowLevel有三种形式,并且是CGFloat类型的

UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal;
UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert;
UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar __TVOS_PROHIBITED;

它们的值可以分别通过打印来验证

NSLog(@"%f  %f  %f",UIWindowLevelNormal,UIWindowLevelAlert,UIWindowLevelStatusBar);

0.000000 2000.000000 1000.000000
这个属性是干啥的

属性等级.png

也就是可以通过这个属性来判断是不是优先显示UIWindow。默认的window的windowLevel是UIWindowLevelNormal,也就是0;
下面我们通过小Demo进行验证
1、首先验证苹果头文件中的UIWindow的windowLevel是多少

AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSLog(@"UIWindowLevelNormal = %f  UIWindowLevelAlert = %f  UIWindowLevelStatusBar = %f  appDelegate.window.windowLevel = %f",UIWindowLevelNormal,UIWindowLevelAlert,UIWindowLevelStatusBar,appDelegate.window.windowLevel);

验证结果

UIWindowLevelNormal = 0.000000  UIWindowLevelAlert = 2000.000000  UIWindowLevelStatusBar = 1000.000000  appDelegate.window.windowLevel = 0.000000

2、验证系统通过UIWindow的windowLevel大小不同优先显示不同的UIWindow
需要注意的是,UIWindow的创建和UIView不同,UIWindow一旦被创建他就会添加到整个界面上。
如果你创建的UIWindow没有显示,请参考:
http://www.jianshu.com/p/75befce85623

创建不同的windowLevel查看相关的效果,代码如下

#import "ViewController.h"
@interface ViewController ()
// 创建属性
@property (nonatomic, strong)UIWindow *myWindow1;
@property (nonatomic, strong)UIWindow *myWindow2;
@property (nonatomic, strong)UIWindow *myWindow3;
@end
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // 创建测试按钮
    UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeSystem];
    tempBtn.frame = CGRectMake(100, 100, 100, 100);
    tempBtn.backgroundColor = [UIColor cyanColor];
    // 通过按钮的点击事件生成不同windowLevel级别的window
    [tempBtn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:tempBtn];
}

按钮的单击事件调用test1
创建一个比默认window的windowLevel大的window来看一下什么效果,效果是会盖在原来的window上面

/**
 *  这个方法证明两个问题
 *1、创建 window 不用添加到任何的控件上面,直接创建完毕就能添加
 *2、创建一个比默认window的windowLevel大的window来看一下什么效果,效果是会盖在原来的window上面
 */
- (void)test1
{
    // 创建window
    if (self.myWindow1 == nil) {
        self.myWindow1 = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        
        UIButton *windowBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [windowBtn setTitle:@"window1点我隐藏" forState:UIControlStateNormal];
        windowBtn.backgroundColor = [UIColor redColor];
        windowBtn.frame = CGRectMake(100, 300, 100, 100);
        [windowBtn addTarget:self action:@selector(clickWindowBtn:) forControlEvents:UIControlEventTouchUpInside];
        [self.myWindow1 addSubview:windowBtn];
        
    }
    // 设置window的颜色,这里设置成半透明的,方便查看window的层级关系
    self.myWindow1.backgroundColor = [UIColor colorWithRed:0.00f green:1.00f blue:0.01f alpha:0.50f];
    // 设置 window 的 windowLevel
    self.myWindow1.windowLevel = 100;
    self.myWindow1.hidden = NO;
}

效果图:


Paste_Image.png

按钮的单击事件调用test2
创建一个和默认window的windowLevel一样大的window来看一下什么效果,效果是会盖在原来的window上面

/**
 *  这个方法证明两个问题
 *1、创建 window 不用添加到任何的控件上面,直接创建完毕就能添加
 *2、创建一个和默认window的windowLevel一样大的window来看一下什么效果,效果是会盖在原来的window上面
 */
- (void)test2
{
    // 创建window
    if (self.myWindow2 == nil) {
        self.myWindow2 = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        
        UIButton *windowBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [windowBtn setTitle:@"window2点我隐藏" forState:UIControlStateNormal];
        windowBtn.backgroundColor = [UIColor greenColor];
        windowBtn.frame = CGRectMake(100, 300, 200, 100);
        [windowBtn addTarget:self action:@selector(clickWindow2Btn:) forControlEvents:UIControlEventTouchUpInside];
        [self.myWindow2 addSubview:windowBtn];
        
    }
    // 设置window的颜色,这里设置成半透明的,方便查看window的层级关系
    self.myWindow2.backgroundColor = [UIColor colorWithRed:0.91f green:0.13f blue:0.13f alpha:0.50f];

    // 设置 window 的 windowLevel,设置的和当前存在的window一样
    self.myWindow2.windowLevel = self.view.window.windowLevel;
    self.myWindow2.hidden = NO;
    [self.myWindow2 makeKeyAndVisible];
}

效果图


Paste_Image.png

按钮的单击事件调用test3
创建一个和默认window的windowLevel一样大的window来看一下什么效果,效果是会在在原来的window下面

/**
 *  这个方法证明两个问题
 *1、创建 window 不用添加到任何的控件上面,直接创建完毕就能添加
 *2、创建一个和默认window的windowLevel一样大的window来看一下什么效果,效果是会在在原来的window下面
 */

- (void)test3
{
    // 为了展示相关的效果,把当前的window的透明度设置为0.5
    self.view.window.alpha = 0.5;
    
    // 创建window
    if (self.myWindow3 == nil) {
        self.myWindow3 = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    }
    // 设置window的颜色,这里设置成半透明的,方便查看window的层级关系
    self.myWindow3.backgroundColor = [UIColor blueColor];
    
    // 设置 window 的 windowLevel,设置的比当前存在的window的小
    self.myWindow3.windowLevel = -1;
    self.myWindow3.hidden = NO;
    [self.myWindow3 makeKeyAndVisible];
}

执行效果:


Paste_Image.png

调用完test方法可以查看当前一共有几个window,并且查看当前的测试window有没有实例化成功,所有的实例化的window并且声明周期够长,可以在[UIApplication sharedApplication].windows找到。

// 查看当前所有的window
NSLog(@"当前所有的window = %@ \nself.myWindow1 = %@",[UIApplication sharedApplication].windows,self.myWindow3);

通过以上总结如下:
1、UIWindowLevel的值不仅仅只有UIWindowLevelNormal、UIWindowLevelAlert、UIWindowLevelStatusBar 这三个,可以通过test3看出,只要你想可以是随意值,负数都可以。
2、UIWindow的显示的确可以通过UIWindowLevel来区分优先级,所有的window都会被加在界面上,只不过会通过优先级罗列起来,UIWindowLevel大的在上面显示,UIWindowLevel小的在下面显示。
3、UIWindowLevel优先级相等的情况下,看谁后实例化了,谁后实例化谁先显示

说了这么多了,有啥应用场景吗?
我想到的有如下场景
1、可以看到蚂蚁聚宝app每次压入后台的时候上面都有一层毛玻璃,我觉得可以用一个window搞一下。
2、其实系统的UIAlertView弹框的显示就是在自己创建的一个Window上面显示的<可以用alertView.window和当前的window比较,发现不是一个window,并且alertView.window.windowLevel大于0>,那么自定义的弹框或者其他也可以通过这个思路来搞一下。并且可以随时随地的销毁获取。
3、或者说每次有单独显示的界面也可以搞个window

代码链接参考:https://github.com/RunOfTheSnail/UIWindowDemo001

以上是我自己根据相关的运行效果总结的,如果有哪位大神觉得有地方描述的不准确,欢迎指正哈,在下感激不尽!!!
还有其他的应用的话欢迎补充。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容