转载于  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:nilcancelButtonTitle:@"OK"otherButtonTitles:@"Cancel", nil];[alertView show];UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"ActionSheet"delegate:nilcancelButtonTitle:@"Cancel"destructiveButtonTitle:@"Don't do that!"otherButtonTitles:@"Hello Wolrd", nil];[actionSheet showInView:self.view];

  下面是程序运行截图:

  根据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 textfieldUITextField *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也是可以接受键盘消息,这一点和文档上说的不太一样。(文档也没说必须是KeyWindow才能接受键盘消息)

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

  UIWindowDidBecomeVisibleNotification

  UIWindowDidBecomeHiddenNotification

  UIWindowDidBecomeKeyNotification

  UIWindowDidResignKeyNotification

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

  代码如下:

//
//  SvUIWindowViewController.m
//  SvUIWindowSample
//
//  Created by  maple on 11/14/12.
//  Copyright (c) 2012 maple. All rights reserved.
//#import "SvUIWindowViewController.h"
#import "SvCustomWindow.h"@interface SvUIWindowViewController ()- (void)presentAlertView;
- (void)presentActionSheet;// observer
- (void)registerObserver;
- (void)unregisterObserver;// observer handler
- (void)windowBecomeKey:(NSNotification*)noti;
- (void)windowResignKey:(NSNotification*)noti;
- (void)windowBecomeVisible:(NSNotification*)noti;
- (void)windowBecomeHidden:(NSNotification*)noti;@end@implementation SvUIWindowViewController- (void)viewDidLoad
{[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.[self registerObserver];// add a textfieldUITextField *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];
}- (void)viewDidUnload
{[super viewDidUnload];// Release any retained subviews of the main view.[self unregisterObserver];
}- (void)viewDidAppear:(BOOL)animated
{[super viewDidAppear:animated];//    [self presentAlertView];//    [self presentActionSheet];
}- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}#pragma mark -
#pragma mark observer- (void)registerObserver
{[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowBecomeKey:) name:UIWindowDidBecomeKeyNotification object:nil];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowResignKey:) name:UIWindowDidResignKeyNotification object:nil];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowBecomeVisible:) name:UIWindowDidBecomeVisibleNotification object:nil];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowBecomeHidden:) name:UIWindowDidBecomeHiddenNotification object:nil];
}- (void)unregisterObserver
{[[NSNotificationCenter defaultCenter] removeObserver:self];
}#pragma mark -
#pragma mark Test AlertView & ActionSheet- (void)presentAlertView
{UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Alert View"message:@"Hello Wolrd, i'm AlertView!!!"delegate:nilcancelButtonTitle:@"OK"otherButtonTitles:@"Cancel", nil];[alertView show];[alertView release];
}- (void)presentActionSheet
{UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"ActionSheet"delegate:nilcancelButtonTitle:@"Cancel"destructiveButtonTitle:@"Don't do that!"otherButtonTitles:@"Hello Wolrd", nil];[actionSheet showInView:self.view];[actionSheet release];
}#pragma mark -
#pragma mark Notification handler- (void)windowBecomeKey:(NSNotification*)noti
{UIWindow *window = noti.object;NSArray *windows = [UIApplication sharedApplication].windows;NSLog(@"current window count %d", windows.count);NSLog(@"Window has become keyWindow: %@, window level: %f, index of windows: %d", window, window.windowLevel, [windows indexOfObject:window]);
}- (void)windowResignKey:(NSNotification*)noti
{UIWindow *window = noti.object;NSArray *windows = [UIApplication sharedApplication].windows;NSLog(@"current window count %d", windows.count);NSLog(@"Window has Resign keyWindow: %@, window level: %f, index of windows: %d", window, window.windowLevel, [windows indexOfObject:window]);
}- (void)windowBecomeVisible:(NSNotification*)noti
{UIWindow *window = noti.object;NSArray *windows = [UIApplication sharedApplication].windows;NSLog(@"current window count %d", windows.count);NSLog(@"Window has become visible: %@, window level: %f, index of windows: %d", window, window.windowLevel, [windows indexOfObject:window]);
}- (void)windowBecomeHidden:(NSNotification*)noti
{UIWindow *window = noti.object;NSArray *windows = [UIApplication sharedApplication].windows;NSLog(@"current window count %d", windows.count);NSLog(@"Window has become hidden: %@, window level: %f, index of windows: %d", window, window.windowLevel, [windows indexOfObject:window]);
}@end

  


iOS 6:


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在隐藏掉

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


iOS7


2014-10-29 15:57:59.922 TestWindowLevel[44895:60b] current window count 1
2014-10-29 15:57:59.924 TestWindowLevel[44895:60b] Window has become visible: <UIWindow: 0x8c56810; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x8c58f90>; layer = <UIWindowLayer: 0x8c57650>>, window level: 0.000000, index of windows: 0
2014-10-29 15:57:59.925 TestWindowLevel[44895:60b] current window count 1
2014-10-29 15:57:59.925 TestWindowLevel[44895:60b] Window has become keyWindow: <UIWindow: 0x8c56810; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x8c58f90>; layer = <UIWindowLayer: 0x8c57650>>, window level: 0.000000, index of windows: 0
2014-10-29 15:58:00.071 TestWindowLevel[44895:60b] current window count 1
2014-10-29 15:58:00.072 TestWindowLevel[44895:60b] Window has Resign keyWindow: <UIWindow: 0x8c56810; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x8c58f90>; layer = <UIWindowLayer: 0x8c57650>>, window level: 0.000000, index of windows: 0
2014-10-29 15:58:00.073 TestWindowLevel[44895:60b] current window count 1
2014-10-29 15:58:00.073 TestWindowLevel[44895:60b] Window has become keyWindow: <_UIModalItemHostingWindow: 0x8c1fc40; frame = (0 0; 320 568); alpha = 0; hidden = YES; gestureRecognizers = <NSArray: 0x8c59190>; layer = <UIWindowLayer: 0x8c59600>>, window level: 0.000000, index of windows: 2147483647
2014-10-29 15:58:00.081 TestWindowLevel[44895:60b] current window count 1
2014-10-29 15:58:00.145 TestWindowLevel[44895:60b] Window has become visible: <_UIModalItemHostingWindow: 0x8c1fc40; frame = (0 0; 320 568); alpha = 0; gestureRecognizers = <NSArray: 0x8c59190>; layer = <UIWindowLayer: 0x8c59600>>, window level: 0.000000, index of windows: 2147483647

1、iOS6和iOS7中苹果对UIAlert和UIActionSheet的实现有所不同。

2、UIApplication中windows  在iOS6和iOS7中有区别。

iOS6:

This property returns an array of the application's visible and hidden windows. The windows are ordered back to front.

iOS7:

This property contains the UIWindow objects currently associated with the app. This list does not include windows created and managed by the system, such as the window used to display the status bar.(当然也不包括UIAlertView和UIActionSheet).

The windows in the array are ordered from back to front by window level; thus, the last window in the array is on top of all other app windows.

转载于:https://www.cnblogs.com/lovelanjuan/p/4059815.html

(转载+ 修改) 深入理解UIWindow相关推荐

  1. String内容不能改变的理解 String的值不能修改的理解

    String内容不能改变的理解 String的值不能修改的理解     java中,String类的值声明后是不能修改,有些初学者就难以理解,为什么下面程序明明是修改了String对象的内容,为什么还 ...

  2. 【转载】全面理解javascript的caller,callee,call,apply概念(修改版)

    今天写PPlayer,发现有段代码引起了我的兴趣: var Class = { create: function() { return function() { this.initialize.app ...

  3. 【转载】C# 理解泛型

    术语表 generics:泛型 type-safe:类型安全 collection: 集合 compiler:编译器 run time:程序运行时 object: 对象 .NET library:.N ...

  4. 使用svnsync备份详解[转载+修改]

    使用svnsync备份很简单,步骤如下: 一.在备份机上创建一个空库:svnadmin create SMP 二.更改该库的钩子脚本pre-revprop-change(因为svnsync要改这个库的 ...

  5. (转载)深入理解Linux中内存管理---分段与分页简介

    首先,必须要阐述一下这篇文章的主题是Linux内存管理中的分段和分页技术. 来回顾一下历史,在早期的计算机中,程序是直接运行在物理内存上的.换句话说,就是程序在运行的过程中访问的都是物理地址.如果这个 ...

  6. (转载)深入理解WeakHashmap

    WeakHashmap (一) 查看API文档,WeakHashmap要点如下: 1. 以弱键 实现的基于哈希表的 Map.在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目.更 ...

  7. (转载)如何理解RxJava中的join操作

    转载:http://avenwu.net/2016/05/10/understand-the-join-operation-in-rx/ 前言 先前写过一篇文章,介绍Rx中不容易理解的概念(Rx那些不 ...

  8. Tensorflow object detection API 搭建属于自己的物体识别模型(转载修改)

    Tensorflow object detection API 搭建属于自己的物体识别模型 电脑配置信息 开始搭建环境 测试自带案例 准备训练图片 配置文件与模型 开始训练模型 生成最终的训练文件 测 ...

  9. 朴素贝叶斯分类器的应用-转载加我的理解注释

    2019独角兽企业重金招聘Python工程师标准>>> 生活中很多场合需要用到分类,比如新闻分类.病人分类等等. 本文介绍朴素贝叶斯分类器(Naive Bayes classifie ...

最新文章

  1. 自定义Kettle数据库插件
  2. Java SE 6 新特性: Java DB 和 JDBC 4.0
  3. 【VC基础】3、配置参数文件
  4. (JAVA)List
  5. hibernate mysql cascade_Hibernate第五篇【inverse、cascade属性详解】
  6. .NET进阶系列之一:C#正则表达式整理备忘
  7. typecho 去掉index.php,Typecho设置伪静态去掉url中的index.php
  8. OSI参考模型(应用层、表示层、会话层、传输层、网络层、数据链路层、物理层)...
  9. 计算机科学渗透信息论的思想,信息系统思想在高中地理课程教学中的渗透方法分析...
  10. linux下搭建DNS子域及相关授权详解
  11. 关于SIM900A模块的学习心得
  12. 服务器虚拟化的重要性,服务器虚拟化:虚拟机迁移的重要性
  13. 模块化的机器学习系统就够了吗?Bengio师生告诉你答案
  14. 我眼中的“阿里月饼事件”
  15. Spark视频王家林大神第1课: 30分钟彻底理解Spark核心API发展史:RDD、DataFrame、DataSet
  16. 青岛科技大学计算机转专业,2021年青岛科技大学大一新生转专业及入学考试相关规定...
  17. vue实现消息提示框
  18. 识别 零极点 matlab,matlab计算零极点分布图
  19. Echo写入一句话木马+分段写入
  20. 惠普800g1支持什么内存_做工精够迷你 惠普EliteDesk800G1评测

热门文章

  1. 東方茸回廊 汉化补丁
  2. javascript函数作用域与闭包
  3. Microsoft月度中文速递
  4. Servlet——ServletConfig
  5. Beta阶段第二次冲刺
  6. java父类调用被子类重写的方法
  7. UpdatePanel AsyncPostBackTrigger PostBackTrigger 区别
  8. node.js+express,实现RESTful API
  9. 装完Windows 7后开启硬盘AHCI模式的方法
  10. sqlserver中,如果正确得到中文的长度