UIWindow

一、简介

<<UIWindow类定义,管理和协调的Windows应用程序显示在屏幕上的对象(如Windows)。一个窗口的两个主要职能是,为显示其意见面积和分发活动的意见。窗口是在视图层次的根。一个窗口属于一个级别;一个级别的窗口出现另一个层面以上。例如,警报出现高于正常的窗口。通常情况下,只有一个在IOS应用程序的窗口

<<UIWindow :UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow

<<继承关系:UIWindow --> UIView -->UIResponder-->NSObject

<<它包含了应用中的可见内容;

<<它在视图和应用对象之间传递触摸事件中起很重要的作用;

<<它和视图控制器配合完成方向转变

      在iOS系统中,windows没有标题栏、关闭框以及其他可视控件。一个window就是一个或多个视图的空白容器,而且应用不能通过window来改变自己的显示内容。当你想要改变现显示容的时候,改变最上层的视图就可以了。

    大多数iOS应用在其生命周期内只使用一个window,这个window从应用的主nib文件中加载,铺满整个主屏幕。当然,如果你的应用支持外部显示,它会额外创建一个window,用于外部显示。系统会创建其他典型的window,一般是在响应特殊事件时创建,例如来电显示。

格式为

1--> 设置根视图(属性的作用

[self.window.rootviewcontroller=vc];;   (这是具体的例子

@property(nullable, nonatomic,strong) UIViewController *rootViewController NS_AVAILABLE_IOS(4_0); // 设置根视图, 默认是空的   (这是属性的说明

二、UIWindow的创建和配置

可以代码或者InterfaceBuilder来创建并设置window。您在启动时创建了窗口,并应保留它,并将其保存到应用程序代理对象中的引用。如果需要额外的window,则在需要用的时候创建即可。

    创建window不需要考虑应用实在前台启动还是后台启动。创建和设置一个window不需要花太多资源。如果程序直接在后台启动,那么你就不能让window可见,直到window到前台之后再让其可见

1、InterfaceBuilder创建UIWindow

用IB创建window非常简单,因为Xcode的工程模板可以替你你创建。每个应用都会包含一个主XIB文件,这个XIB就包含了一个主window。另外,这些模板也为window在应用的代理对象中定义了outlet,你可以在代码中通过outlet取到window对象。

注意:在使用IB创建window的时候,应该在属性设置栏中设置为全屏。如果没有设置为全屏,且window小于手机的屏幕尺寸,那么一些视图的触摸时间肯接收不到。这是因为window接受不到自己区域以外的触摸事件。如果视图的触摸点没在window的区域范围内,则响应不到触摸事件。所以要确保window是全屏。

    如果你重构代码时用到 IB添加window,也很简单,像XIB文件中拖一个window对象,然后进行如下操作:

要在运行时访问window,应该把window和outlet相连。outlet一般情况下是在application delegate中,也可以是这个NIB文件对应的代码文件。

重构过程中如果需要新建一个主NIB,那就得在info.plist文件中设置NSMainNibFil键。通过设置NSMainNibFil的值来确保这个window在代理方法application:didFinishLaunchingWithOptions:被调用是得到加载。

2、纯代码创建window



上面代码中的self.window,是在application delegate中已经声明过得属性,用来保存window对象。如果你创建的是用于外部显示的window,应该给它重新命名,并且需要设置bounds。

 创建window的时候,要把bounds设置为屏幕大小,不能有任何缩减

三、将view添加到UIWindow

1、直接将控制器的view添加到UIWindow中,并不理会它对应的控制器

[self.window  addsubview:vc.view];

直接将view通过addSubview方式添加到window中,程序负责维护view的生命周期以及刷新,但是并不会为去理会view对应的ViewController,因此采用这种方法将view添加到window以后,我们还要保持view对应的ViewController的有效性,不能过早释放。

2、设置uiwindow的根控制器,自动将rootviewcontroller的view添加到window中,负责管理rootviewcontroller的生命周期

[self.window.rootviewcontroller=vc];

rootViewController时UIWindow的一个遍历方法,通过设置该属性为要添加view对应的ViewController,UIWindow将会自动将其view添加到当前window中,同时负责ViewController和view的生命周期的维护,防止其过早释放


<注意>建议使用(2).因为方法(1)存在一些问题,比如说控制器上面可能由按钮,需要监听按钮的点击事件,如果是1,那么按钮的事件应该由控制器来进行管理。但控制器是一个局部变量,控制器此时已经不存在了,但是控制器的view还在,此时有可能会报错。注意:方法执行完,这个控制器就已经不存在了。

问题描述1:当view发生一些事件的时候,通知控制器,但是控制器已经销毁了,所以可能出现未知的错误。

问题描述2:添加一个开关按钮,让屏幕360度旋转(两者的效果不一样)。当发生屏幕旋转事件的时候,UIapplication对象会将旋转事件传递给uiwindow,uiwindow又会将旋转事件传递给它的根控制器,由根控制器决定是否需要旋转

UIapplication->uiwindow->根控制器(第一种方式没有根控制器,所以不能跟着旋转)。

提示:不通过控制器的view也可以做开发,但是在实际开发中,不要这么做,不要直接把view添加到UIWindow上面去。因为,难以管理。

四、获取window

1、主窗口和次窗口

【self.window makekeyandvisible】让窗口成为主窗口,并且显示出来。有这个方法,才能把信息显示到屏幕上。

   因为Window有makekeyandvisible这个方法,可以让这个Window凭空的显示出来,而其他的view没有这个方法,所以它只能依赖于Window,Window显示出来后,view才依附在Window上显示出来。

【self.window make keywindow】//让uiwindow成为主窗口,但不显示。

2.获取UIwindow

1)[UIApplication sharedApplication].windows  在本应用中打开的UIWindow列表,这样就可以接触应用中的任何一个UIView对象(平时输入文字弹出的键盘,就处在一个新的UIWindow中)

(2)[UIApplication sharedApplication].keyWindow(获取应用程序的主窗口)用来接收键盘以及非触摸类的消息事件的UIWindow,而且程序中每个时刻只能有一个UIWindow是keyWindow。

提示:如果某个UIWindow内部的文本框不能输入文字,可能是因为这个UIWindow不是keyWindow

(3)view.window获得某个UIView所在的UIWindow

五、UIWindow的视图属性(属性的顺序与苹果API一致)

1-->设置Screen

        self.window.screen = self.externalScreen;  

@property(nonatomic,strong) UIScreen *screen NS_AVAILABLE_IOS(3_2);//默认是[UIScreen mainScreen]。改变屏幕可能是一个昂贵的操作,不应该在性能敏感的代码中完成

2-->设置视图层级

self.window.windowLevel = UIWindowLevelAlert+1;

@property(nonatomic) UIWindowLevel windowLevel; // 默认为0

<注意>UIWindow在显示的时候会根据UIWindowLevel进行排序的,即Level高的将排在所有Level比他低的层级的前面。下面我们来看UIWindowLevel的定义:

                const   UIWindowLevel UIWindowLevelNormal; 默认为0    

    const UIWindowLevel UIWindowLevelAlert;默认为2000

    const UIWindowLevel UIWindowLevelStatusBar;默认为1000

    typedef CGFloat UIWindowLevel;

Normal ,StatusBar,Alert.输出他们三个层级的值,我们发现从左到右依次是0,1000,2000,也就是说Normal级别是最低的,StatusBar处于中级,Alert级别最高。而通常我们的程序的界面都是处于Normal这个级别的,系统顶部的状态栏应该是处于StatusBar级别,提醒用户等操作位于Alert级别。根据window显示级别优先原则,级别高的会显示在最上层,级别低的在下面,我们程序正常显示的view在最底层;

3-->是否为根视图(只读属性)

BOOL  isKeyWindow=self.window.keyWindow;

@property(nonatomic,readonly,getter=isKeyWindow) BOOL keyWindow;

4-->becomeKeyWindow

- (void)becomeKeyWindow; //该方法不应该被手动调用,当window变为keyWindow时会被自动调用来通知window。可以继承UIWindow重写此方法来实现功能

5-->resignKeyWindow

- (void)resignKeyWindow; // 该方法不应该被手动调用,当window不再是keyWindow时(例如其他window实例调用了- makeKeyWindow或- makeKeyAndVisible方法)会被自动调用来通知window。可以继承UIWindow重写此方法来实现功能。

6-->让当前UIWindow变成keyWindow,默认不显示

  [self.window makeKeyWindow];

- (void)makeKeyWindow; // 让window成为keyWindow(主窗口),默认不可见

7-->让当前UIWindow变成keyWindow,并显示出来

 [self.window makeKeyAndVisible];

- (void)makeKeyAndVisible;//  让当前UIWindow变成keyWindow,并显示出来

8-->设置uiwindow的根控制器

[self.window.rootviewcontroller=vc];

@property(nullable, nonatomic,strong) UIViewController *rootViewController NS_AVAILABLE_IOS(4_0);//  根控制器

9-->分发自定义事件

UIApplication 和 UIWindow 有方法 - sendEvent: ,用于把事件分发到 hitTest View

UIApplication == sendEvent: ==> UIWindow == sendEvent: ==> hitTest View

- (void)sendEvent:(UIEvent *)event;//UIApplication调用window的该方法给window分发事件,window再将事件分发到合适的目标,比如将触摸事件分发到真正触摸的view上。可以直接调用该方法分发自定义事件。

10-->把该window中的一个坐标转换成在目标window中时的坐标值

CGPoint p = [self.window1 convertPoint:CGPointMake(0, 0) toWindow:self.window0];

- (CGPoint)convertPoint:(CGPoint)point toWindow:(nullable UIWindow *)window;

11-->把目标window中的一个坐标转换成在该window中时的坐标值

CGPoint p = [self.window1 convertPoint:CGPointMake(0, 0) fromWindow:self.window0];

- (CGPoint)convertPoint:(CGPoint)point fromWindow:(UIWindow *)window;

12-->把该window中的一个矩阵转换成在目标window中时的矩阵值

CGRect rect=[self.window convertRect:CGRectMake(0, 0, 0, 0) toView:self.window0];

- (CGRect)convertRect:(CGRect)rect toWindow:(UIWindow *)window;  

13--> 把目标window中的一个矩阵转换成在该window中时的矩阵值

 CGRect rect=[self.window convertRect:CGRectMake(0, 0, 0, 0) toView:self.window0];

- (CGRect)convertRect:(CGRect)rect fromWindow:(UIWindow *)window;

六、UIWindow的常量属性

1-->UIWindowLevel的枚举

UIWindowLevelNormal;// 0.000000

UIWindowLevelStatusBar;// 1000.000000

UIWindowLevelAlert;// 2000.000000

2-->监测window的通知名称:

UIKIT_EXTERN NSString *const UIWindowDidBecomeVisibleNotification; // 当window激活时并展示在界面的时候触发,返回空

UIKIT_EXTERN NSString *const UIWindowDidBecomeHiddenNotification;  // 当window隐藏的时候触发,暂时没有实际测,返回空

UIKIT_EXTERN NSString *const UIWindowDidBecomeKeyNotification;    // 当window被设置为keyWindow时触发,返回空

UIKIT_EXTERN NSString *const UIWindowDidResignKeyNotification;    // 当window的key位置被取代时触发,返回空

3-->监测键盘的通知名称:

UIKIT_EXTERN NSString *const UIKeyboardWillShowNotification;// 显示键盘的时候立即发出该通知

UIKIT_EXTERN NSString *const UIKeyboardDidShowNotification;//显示键盘后才发出该通知

UIKIT_EXTERN NSString *const UIKeyboardWillHideNotification;//键盘即将消失的时候立即发出该通知

UIKIT_EXTERN NSString *const UIKeyboardDidHideNotification;//键盘消失后才发出该通知

UIKIT_EXTERN NSString *const UIKeyboardWillChangeFrameNotification  NS_AVAILABLE_IOS(5_0);//键盘的frame值发生变化的时候立即发出该通知

UIKIT_EXTERN NSString *const UIKeyboardDidChangeFrameNotification  NS_AVAILABLE_IOS(5_0);//键盘的frame值发生变化后才发出该通知

4-->userInfo字典中key为:

NSString *const UIKeyboardFrameBeginUserInfoKey;//userInfo字典里该key对应一个NSValue,存储一个包含键盘初始frame值的CGRect结构(即键盘刚出现时的frame值)

NSString *const UIKeyboardFrameEndUserInfoKey;//userInfo字典里该key对应一个NSValue,存储一个包含键盘结束frame值的CGRect结构(即键盘动画结束后的frame值)

NSString *const UIKeyboardAnimationDurationUserInfoKey;//userInfo字典里该key对应一个NSNumber,存储一个包含键盘进入或离开屏幕的UIViewAnimationCurve结构

NSString *const UIKeyboardAnimationCurveUserInfoKey;//userInfo字典里该key对应一个NSNumber,存储一个包含键盘动画时间的double值,时间以秒为单位。

例如,在UIKeyboardWillShowNotification,UIKeyboardDidShowNotification通知中的userInfo内容为

userInfo = {

    UIKeyboardAnimationCurveUserInfoKey = 0;

    UIKeyboardAnimationDurationUserInfoKey = "0.25";

    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";

    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 588}";

    UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";

    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";

    UIKeyboardFrameChangedByUserInteraction = 0;

    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";

}

参考:

IOS: iPhone键盘通知与键盘定制

UIKit-UIWindow详解

UIWindow 详解及使用场景

【iOS】UIWindow中文详解

IOS学习记录 基础类UIWindow,UIView,UISreen篇

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

推荐阅读更多精彩内容

  • UIView的功能 负责渲染区域的内容,并且响应该区域内发生的触摸事件 UIWindow 在iOS App中,UI...
    小蘑菇2阅读 773评论 4 5
  • 一、UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow。 iOS程序启动完毕后...
    MrLXQ阅读 1,056评论 0 3
  • 每一个IOS程序都有一个UIWindow,在我们通过模板简历工程的时候,xcode会自动帮我们生成一个window...
    jumping鹏阅读 1,006评论 0 0
  • 概念: UIWindw定义了一个负责管理,协调一个App的View是如何显示在设备屏幕上的窗口类,除非一个App可...
    Harely阅读 867评论 0 1
  • 170918【读书 day190】《与奇人相遇》 葛吉夫 45m 今天看的两个章节中,描述了葛吉夫先生很多生意上的...
    水若_小水呓梦阅读 215评论 0 0