1.UIWindow简介

UIWindow是一种特殊的UIView,通常在一个app中至少会有一个UIWindow。

iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的View,最后将控制器的View添加到UIWindow上,于是控制器的View就显示在屏幕上了。

一个iOS程序之所以能显示在屏幕上,完全是因为它有UIWindow,也就是说,没有UIWindow就看不到任何UI界面。

状态栏和键盘都是特殊的UIWindow。

那么UIWindow是如何将View显示到屏幕上的呢

这里有三个重要的对象UIScreen,UIWindow,UIView。

UIScreen对象识别物理屏幕连接到设备

UIWindow对象提供绘画支持给屏幕

UIView执行绘画,当窗口要显示内容的时候,UIView绘画出他们的内容并附加到窗口上。

这样View就显示在窗口上了

2.UIWindow的创建

1.UIWindow是什么时候创建的?

我们可以发现,当我们新建一个项目,直接在stroyboard为view设置一个背景颜色,然后运行项目,就能看到换了背景颜色的view,这说明系统已经帮我们创建了一个UIWindow,那么这个UIWindow是什么时候创建的?

我们找到程序的入口main函数,来看程序的启动过程

int main(int argc, char * argv[]) {

@autoreleasepool {

return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

}

}

此时我们可以根据UIApplicationMain函数了解程序启动的过程

根据传递的类名创建UIApplication对象,这是第一个对象

创建UIApplication代理对象,并给UIApplicaiton对象设置代理

开启主运行循环 main events loop处理事件,保持程序一直运行

加载info.plist,判断是否指定mian(xib 或者 storyboard)如果指定就去加载

当我们把指定的Main Interface 中mian给删除的时候,重新运行程序,就会发现我们之前设置的view没有办法显示了。

Main Interface 中 Main删除

此时我们基本可以想到,UIWindow应该是在加载storyboard的时候系统创建的,那么系统是如何加载storyboard的呢?

系统在加载storyboard的时候会做以下三件事情

创建窗口

加载mian.storyboard 并实例化view controller

分配新视图控制器到窗口root viewcontroller,然后使窗口显在示屏幕上。

因此,当系统加载完info.plist,判断后发现没有main,就不会加载storyboard,也就不会帮我们创建UIWindow,那么我们需要自己在程序启动完成的时候也就是在didFinishLaunchingWithOptions方法中创建。

2.如何创建UIWindow?

首先根据系统加载storyboard时做的三件事情,我们可以总结出UIWindow创建步骤

创建窗口对象

创建窗口的根控制器,并且赋值

显示窗口

并且我们在AppDelegate.h中发现属性window

@property (strong, nonatomic) UIWindow *window;

那么我们来看一下如何创建UIWindow

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

//创建窗口对象

self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];

//创建窗口的根控制器,并且赋值

UIViewController *rootVc = [[UIViewController alloc]init];

self.window.rootViewController = rootVc;

//显示窗口

[self.window makeKeyAndVisible];

return YES;

}

窗口显示注意点:

我们看到系统为我们创建的window属性是strong强引用,是为了不让窗口销毁,所以需要强引用

窗口的尺寸必须设置,一般设置为屏幕大小。

[self.window addsubview:rootVc.view];可直接将控制器的view添加到UIWindow中,并不理会它对应的控制器,但是这种方法违背了MVC原则,当我们需要处理一些业务逻辑的时候就很麻烦了。

当发生屏幕旋转事件的时候,UIapplication对象会将旋转事件传递给UIWindow,UIWindow又会将旋转事件传递给它的根控制器,由根控制器决定是否需要旋转。UIapplication对象 -> UIWindow -> 根控制器。

([self.window addsubview:rootVc.view];没有设置根控制器,所以不能跟着旋转)。

设置根控制器可以将对应界面的事情交给对应的控制器去管理。

那么[self.window makeKeyAndVisible];这个方法为什么就能显示窗口呢?我们来看一下[self.window makeKeyAndVisible];的底层实现了哪些功能

可以显示窗口

成为应用程序的主窗口

当我们不调用这个方法,打印self.window。

UIWindow: 0x7f920503cc80; frame = (0 0; 414 736); hidden = YES; gestureRecognizers = ; layer = >

我们可以看到 hidden = YES;那么hidden = NO就可以显示窗口了

另外,我们在[self.window makeKeyAndVisible];前后分别输出一下application.keyWindow

NSLog(@"%@",application.keyWindow);

[self.window makeKeyAndVisible];

NSLog(@"%@",application.keyWindow);

打印内容

UIWindow[6259:1268399] (null)

UIWindow[6259:1268399] ; layer = >

我们可以看到调用[self.window makeKeyAndVisible];方法之后application.keyWindow就有值了,那么[self.window makeKeyAndVisible];的底层实现就很明显了。

可以显示窗口 self.window.hidden = NO;

成为应用程序的主窗口 application.keyWindow = self.window,这个会报错,因为application.keyWindow是readonly,所以我们没有办法直接赋值。

3.通过storyboard加载控制器

刚才我们提到过系统在加载storyboard的时候会做以下三件事情

创建窗口

加载mian.storyboard 并实例化view controller

分配新视图控制器到窗口root viewcontroller,然后使窗口显在示屏幕上。

那么我们用代码来模拟实现一下

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// 1.创建窗口

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

// 2.加载main.storyboard,创建main.storyboard描述的控制器

// UIStoryboard专门用来加载stroyboard

// name:storyboard名称不需要后缀

UIStoryboard *stroyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];

// 加载sotryboard描述的控制器

// 加载箭头指向的控制器

UIViewController *vc = [stroyboard instantiateInitialViewController];

//根据绑定标识加载

//UIViewController *vc = [stroyboard instantiateViewControllerWithIdentifier:@"red"];

// 设置窗口的根控制器

self.window.rootViewController = vc;

// 3.显示窗口

[self.window makeKeyAndVisible];

return YES;

}

3.通过xib加载控制器

通过xib加载控制器和通过storyboard加载控制器类似,直接上代码

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

// 创建窗口的根控制器

// 通过xib创建控制器

ViewController *vc = [[ViewController alloc] initWithNibName:@"VC" bundle:nil];

//vc.view.backgroundColor = [UIColor redColor];

self.window.rootViewController = vc;

[self.window makeKeyAndVisible];

return YES;

}```

## 3.UIWindow的层级

UIWindow是有层级的,层级高的显示在最外面,当层级相同时,越靠后调用的显示在外面。

UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal; //默认,值为0

UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert; //值为2000

UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar ; // 值为1000

所以`UIWindowLevelNormal < UIWindowLevelStatusBar< UIWindowLevelAlert `

并且层级是可以做加减的`self.window.windowLevel = UIWindowLevelAlert+1;`

**关于UIApplication的介绍可以看这篇文章[iOS-UIApplication详解](http://www.jianshu.com/p/f0a2117406d8)**

`✨本文借鉴了很多前辈的文章,如果有不对的地方请指正,欢迎大家一起交流学习 xx_cc 。`

ios uiwindow弹窗_iOS-UIWindow详解相关推荐

  1. iOS富文本字符串AttributedString详解

    原文链接: iOS富文本字符串AttributedString详解 简书主页:http://www.jianshu.com/users/37f2920f6848 Github主页:https://gi ...

  2. iOS 证书与签名 解惑详解

    iOS 证书与签名 解惑详解 分类: iPhone2012-06-06 19:57 9426人阅读 评论(1) 收藏 举报 iosxcodecryptographyappleiphone测试 目录(? ...

  3. 猎豹浏览器怎么设置允许弹出窗口 允许弹窗设置方法详解

    频频出现的广告弹窗,让不少人选择打开所用浏览器的弹窗拦截功能.不过,此举也带来了一点小麻烦,那就是容易误伤"友军",一些必要的弹窗也会被强制拦截!那么,该怎么解决这一问题呢?下面小 ...

  4. iOS中MVC等设计模式详解

    iOS中MVC等设计模式详解 在iOS编程,利用设计模式可以大大提高你的开发效率,虽然在编写代码之初你需要花费较大时间把各种业务逻辑封装起来.(事实证明这是值得的!) 模型-视图-控制器(MVC)设计 ...

  5. iOS开发之Accounts框架详解

    2019独角兽企业重金招聘Python工程师标准>>> iOS开发之Accounts框架详解 Accounts框架是iOS原生提供的一套账户管理框架,其支持Facebook,新浪微博 ...

  6. iOS申请发布证书-图文详解

    iOS申请发布证书-图文详解 首先登陆https://developer.apple.com 选择iOS Developer program 板块下的 Certificates,Identifiers ...

  7. IOS开发学习笔记-----UILabel 详解

    IOS开发学习笔记-----UILabel 详解 01 //创建uilabel 02 UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMa ...

  8. IOS数据库操作SQLite3使用详解(转)

    iPhone中支持通过sqlite3来访问iPhone本地的数据库. 具体使用方法如下 1:添加开发包libsqlite3.0.dylib 首先是设置项目文件,在项目中添加iPhone版的sqlite ...

  9. IOS数据库操作SQLite3使用详解

    sqlite数据库iosdatabasesqlinteger 目录(?)[+] iPhone中支持通过sqlite3来访问iPhone本地的数据库. 具体使用方法如下 1:添加开发包libsqlite ...

  10. 直播平台软件开发,展示弹窗常见API详解

    直播平台软件开发,展示弹窗常见API详解 showToast 演示代码 wx.showToast({title: "购买失败",icon: "error",du ...

最新文章

  1. C#学习笔记——数据库篇(1)
  2. kdj超卖_一个判断股票超买超卖现象的指标——KDJ,简单明了,准确且省心
  3. 《Python Cookbook 3rd》笔记(2.2):字符串开头或结尾匹配
  4. python新特性_Python3.6正式版新特性预览
  5. u-boot移植随笔:EEPROM移植及测试
  6. oracle 函数 abs,Oracle 函数(八)
  7. mybatis-plus控制台打印SQL
  8. 简单实现x的n次方pta_Day12 :数值的整数次方
  9. 毕设+电路板(BTN7960驱动电路+LM2596/AMS117稳压电路+蜂鸣器+STM32F103C8T6最小系统电路)
  10. html正方形符号,html 特殊符号标记
  11. appcan使用心得体会
  12. DFMA(dfma15发动机怎么样)
  13. OSChina 周二乱弹 ——室友开始买假发女装了
  14. NFT“MetaBunny”公开发售后飙升近35倍 首轮公开发售1000枚后结束
  15. 尚硅谷-谷粒商城-电商项目-秒杀系统-笔记
  16. 爱普生LQ-610K针式打印机不通电维修
  17. Ubuntu安装ibus万能五笔
  18. TFX发展简史/《Towards ML Engineering: A Brief History Of TensorFlow Extended (TFX)》
  19. [转载]WEB中实时时间的显示
  20. 马斯克称特斯拉FSD Beta可紧急倒车,誓要取代合格的人类司机?

热门文章

  1. WebSocket子协议STOMP详解
  2. CentOS 6.3下NFS安装配置
  3. CentOS6.6部署VNC服务端
  4. Ettus Research USRP B200/B210 simple case
  5. 2-1 年会抽奖_实现分析
  6. js时间搓化为今天明天_做猪皮冻,记住“泡一泡,刮一刮,搓一搓”,皮冻晶莹剔透无异味...
  7. c++头文件被c语言调用需要注意什么_嵌入式C语言之模块化编程
  8. Java存储任意对象_浅析java设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象...
  9. 现代ups电源及电路图集_2020山特UPS电源自动开机200KVA实力
  10. oracle 对表重建索引,重建特定Oracle表的所有常规索引