[转]UIWindow的一点儿思考

转自:http://www.cnblogs.com/smileEvday/archive/2012/11/16/UIWindow.html

每一个IOS程序都有一个UIWindow,在我们通过模板简历工程的时候,xcode会自动帮我们生成一个window,然后让它变成keyWindow并显示出来。这一切都来的那么自然,以至于我们大部分时候都忽略了自己也是可以创建UIWindow对象。

  通常在我们需要自定义UIAlertView的时候(IOS 5.0以前AlertView的背景样式等都不能换)我们可以使用UIWindow来实现(设置windowLevel为Alert级别),网上有很多例子,这里就不详细说了。

  我的上一篇文章UIWindowLevel详解,中讲到了关于Windowlevel的东西,当时还只是看了看文档,知道有这么一回儿事。今天刚好遇到这块儿的问题,就顺便仔细看了一下UIWindow方面的东西,主要包括:WindowLevel以及keyWindow两个方面。

一、UIWindowLevel

  我们都知道UIWindow有三个层级,分别是Normal,StatusBar,Alert。打印输出他们三个这三个层级的值我们发现从左到右依次是0,1000,2000,也就是说Normal级别是最低的,StatusBar处于中等水平,Alert级别最高。而通常我们的程序的界面都是处于Normal这个级别上的,系统顶部的状态栏应该是处于StatusBar级别,UIActionSheet和UIAlertView这些通常都是用来中断正常流程,提醒用户等操作,因此位于Alert级别。

  上一篇文章中我也提到了一个猜想,既然三个级别的值之间相差1000,而且我们细心的话查看UIWindow的头文件就会发现有一个实例变量_windowSublevel,那我们就可以定义很多中间级别的Window。例如可以自定义比系统UIAlertView级别低一点儿的window。于是写了一个小demo,通过打印发现系统的UIAlertView的级别是1996,而与此同时UIActionSheet的级别是2001,这样也验证了subLevel的确存在。

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Alert View"
                                                        message:@"Hello Wolrd, i‘m AlertView!!!"
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:@"Cancel", nil];
    [alertView show];
    [alertView release];

    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"ActionSheet"
                                                             delegate:nil
                                                    cancelButtonTitle:@"Cancel"
                                               destructiveButtonTitle:@"Don‘t do that!"
                                                    otherButtonTitles:@"Hello Wolrd", nil];
    [actionSheet showInView:self.view];
    [actionSheet release];

  下面是程序运行截图:

  根据window显示级别优先的原则,级别高的会显示在上面,级别低的在下面,我们程序正常显示的view位于最底层,至于具体怎样获取UIAlertView和UIActionSheet的level,我会在下面第二部分keyWindow中介绍并给出相应的代码。

二、KeyWindow

  什么是keyWindow,官方文档中是这样解释的"The key window is the one that is designated to receive keyboard and other non-touch related events. Only one window at a time may be the key window." 翻译过来就是说,keyWindow是指定的用来接收键盘以及非触摸类的消息,而且程序中每一个时刻只能有一个window是keyWindow。

  下面我们写个简单的例子看看非keyWindow能不能接受键盘消息和触摸消息,程序中我们在view中添加一个UITextField,然后新建一个alert级别的window,然后通过makeKeyAndVisible让它变成keyWindow并显示出来。代码如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.viewController = [[[SvUIWindowViewController alloc] initWithNibName:@"SvUIWindowViewController" bundle:nil] autorelease];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

    UIWindow *window1 = [[UIWindow alloc] initWithFrame:CGRectMake(0, 80, 320, 320)];
    window1.backgroundColor = [UIColor redColor];
    window1.windowLevel = UIWindowLevelAlert;
    [window1 makeKeyAndVisible];

    return YES;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [self registerObserver];

    // add a textfield
    UITextField *filed = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 320, 60)];
    filed.placeholder = @"Input something here";
    filed.clearsOnBeginEditing = YES;
    filed.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:filed];
    [filed release];
}

  运行截图如下:

  从图中可以看出,虽然我们自己新建了一个然后设置为keyWindow并显示,但是点击程序中默认window上添加的textField还是可以唤出键盘,而且还可以正常接受键盘输入,只是键盘被挡住了,说明非keyWindow也是可以接受键盘消息,这一点和文档上说的不太一样。

  观察UIWindow的文档,我们可以发现里面有四个关于window变化的通知:

  UIWindowDidBecomeVisibleNotification

  UIWindowDidBecomeHiddenNotification

  UIWindowDidBecomeKeyNotification

  UIWindowDidResignKeyNotification

  这四个通知对象中的object都代表当前已显示(隐藏),已变成keyWindow(非keyWindow)的window对象,其中的userInfo则是空的。于是我们可以注册这个四个消息,再打印信息来观察keyWindow的变化以及window的显示,隐藏的变动。

  代码如下:

SvUIWindowViewController.m

  a、当我们打开viewDidAppear中“[self presentAlertView];”的时候,控制台输出如下

  根据打印的信息我们可以看出流程如下:

  1、程序默认的window先显示出来

  2、默认的window再变成keyWindow

  3、AlertView的window显示出来

  4、默认的window变成非keyWindow

  5、最终AlertView的window变成keyWindow

  总体来说就是“要想当老大(keyWindow),先从小弟(非keyWindow)开始混起” 而且根据打印的信息我们同事可以知道默认的window的level是0,即normal级别;AlertView的window的level是1996,比Alert级别稍微低了一点儿。

  b、当我们打开viewDidAppear中“[self presentActionSheet];”的时候,控制台输出如下:  

  keyWindow的变化和window的显示和上面的流程一样,同时我们可以看出ActionSheet的window的level是2001。

  c、接着上一步,我们点击弹出ActionSheet的cancel的时候,控制台输出如下:

  我们看出流程如下:

  1、首先ActionSheet的window变成非keyWindow

  2、程序默认的window变成keyWindow

  3、ActionSheet的window在隐藏掉

  总体就是“想隐居幕后可以,但得先交出权利”。

  以上是这两天遇到的,总结一下,欢迎补充,如果有不对的地方也请多多指正。

时间: 2024-07-30 02:24:53

[转]UIWindow的一点儿思考的相关文章

Coding源码学习第二部分(FunctionIntroManager.m)

接上篇.上篇有一个细节忘了写,在Coding_iOS-Info.plist 里面添加了一个key 是 Status bar is initially hidden  Value 是 YES,在application 启动的时候隐藏状态栏,然后在 1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 2 { 3 ...... 4 /

iOS 中Window优先级的问题

在项目中,视频播放时候遇到网络切换需要弹出AlertView提醒用户,忽然发现转屏的时候播放View加到KeyWindow的时候把AleryView挡住了.如图 因为转屏的时候视图是直接加载到 [UIApplication sharedApplication].keyWindow 所以应该是keyWindo切换导致的,因为AlertView弹出时候,keyWindow变成了AlertView的window. 更多请点击UIWindow的一点儿思考 所以解决办法很简单,在添加PlayerView的

Hello World——用思考揭开世界的一角

在开始进入正题之前,还是先按照惯例,介绍一下人物背景. 本人女,92年11月生,是标准的90后,喜欢听周杰伦,最喜欢的作家是大仲马,只读过一点儿韩寒,经历过郭敬明好几版<小时代>的摧残,爱逛街吃饭,带有90后的一些标签,但是也有自己一些特色的东西.大一的时候,是只专心上课,一字一字记笔记,晚上乖乖上自习的好学生,业余的时候看看书,乱写小说.这样的日子大概持续了一个多学期,但是楼主读的只是一个2本小学校,学的是电子,最重要的是,我不喜欢我的专业(这个是当时的想法,现在不能用喜不喜欢这个词了),进

iOS 关于UIWindow 的认识

UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了 一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow.也就说,没有UIWindow,就看不见任何UI界面 如何获取UIWindow (1)[UIApplication sharedApplication].windows

UIWindow的层级问题Level

每一个IOS程序都有一个UIWindow,在我们通过模板简历工程的时候,xcode会自动帮我们生成一个window,然后让它变成keyWindow并显示出来.这一切都来的那么自然,以至于我们大部分时候都忽略了自己也是可以创建UIWindow对象. 通常在我们需要自定义UIAlertView的时候(IOS 5.0以前AlertView的背景样式等都不能换)我们可以使用UIWindow来实现(设置windowLevel为Alert级别),网上有很多例子,这里就不详细说了. 我的上一篇文章UIWind

工作第八个月:从安卓调整到服务端后的思考

前言 客户端开发的侧重点 后端开发的侧重点 浮躁的心 架构师之梦 跳出局限 总结 其他 Thanks 前言 距离写上篇博客已经有一个月了,年后由于岗位调整转去写后台,开发框架.开发模式的不同让我适应了好一阵子,更难的是后端开发与客户端开发的思维习惯的转变. 客户端开发的侧重点 在我看来,客户端开发最重要的是: 业务流程的理解与建议 交互方式的理解与建议 数据的展示(快速.高效) 数据的获取(用户主动输入.UBT 采集) 保证应用的性能(内存.弱网.耗电) 实际工作中,产品经理拿到业务需求后会分析

UIWindow 详解及使用场景

首先来看一下UIWindow 继承关系 UIView的功能  负责渲染区域的内容,并且响应该区域内发生的触摸事件 UIWindow 在iOS App中,UIWindow是最顶层的界面内容,我们使用UIWindow和UIView来呈现界面.UIWindow并不包含任何默认的内容,但是它被当作UIView的容器,用于放置应用中所有的UIView. 从继承关系来看,UIWindow继承自UIView,所以UIWindow除了具有UIView的所有功能之外,还增加了一些特有的属性和方法,而我们最常用的方

UIWindow笔记

Window的作用 在iOS中,一个window(也就是一个UIWindow对象)主要有这样几个作用: 展示app的可视内容: 将事件分发给视图以及其他对象: 和app的view controller一起处理屏幕旋转. 其实在大多数情况下,第三方程序员不用做任何事情,window就能完成这些工作.所以很多时候,只有当这个app需要支持另一个外设的屏幕的时候,程序员才会对window进行操作. UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow iOS程序启动完

Unityclient框架笔记二(组件实体开发模式的思考)

Unity的Entity-Component-System实现的很美丽,很灵活.许多文章也对这样的组件实体的开发模式倍加推崇.由于它契合这么一条规则:优先使用组合而不是继承. 可是实际开发过程中,限制于我的个人能力.想实现一个相同美丽的基于组件的MMO框架是很困难的一件事情. 这篇文章是个人开发过程中的一些思考,实际上.所谓美丽的框架是因人而异的.而且不一定是必须的,可以用自己熟悉的方式高速的完毕项目的开发就足够了.仅仅要开发过程不会感觉别扭,代码也不会把自己或其它人恶心到,策划改动需求的时候不