UIWindow学习

写在前面

本文内容绝大部分都参考唐巧大神的《iOS开发进阶》,只是结合不是特别长的开发经验加以补充;最后基于UIWindow自定义了一个类似于微信的ActionSheet。

UIWindow简介

在iOS App中,UIWindow是最顶层的界面内容,我们使用UIWindow和UIView来呈现界面。UIWindow并不包含任何默认的内容,但是它被当作UIView的容器,用于放置应用中所有的UIView。

从继承关系来看,UIWindow继承自UIView,所以UIWindow除了具有UIView的所有功能之外,还增加了一些特有的属性和方法,而我们最常用的方法,就是在App刚启动时,调用UIWindow的makeKeyAndVisible方法,代码如下:


1

2

3

4

5

6

7

8

9

10

11


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

// Override point for customization after application launch.

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

MainNavigationController *VC = [MainNavigationController sharedMainNavigationController];

self.window.rootViewController = VC;

[self.window makeKeyAndVisible];

return YES;

}

P.S:makeKeyAndVisible方法,从方法名字面上看有两层意思:让window成为key window,使得window可见。

总的来看,UIWindow的主要作用有:

  1. 作为UIView的最顶层容器,包含应用显示所有的UIView;
  2. 传递触摸消息和键盘事件给UIView;

为UIWindow增加UIView

通常我们有两种办法给UIWindow增加子UIView:

  1. 通过调用addSubView方法,因为UIWindow是UIView的子类,所以它可以使用UIView的addSubView方法给自己增加子UIView,从而承担容器的作用;
  2. 通过设置其特有的rootViewController属性。设置该属性后,UIWindow会自动将view controller的view添加到当前window中,同时负责维护view controller和view的生命周期。上述在application:didFinishLaunchingWithOptions:中使用的就是这种办法;

系统对UIWindow的使用

通常在一个程序中只会有一个UIWindow,但有些时候我们调用系统的控件(例如UIAlertView)时,iOS系统为了保证UIAlertView在所有的界面之上,它会临时创建一个新的UIWindow,通过将其UIWindowLevel设置更高,让UIAlertView盖在所有其他UI之上。

为了验证这个说法,在《iOS开发进阶》中,作者还以举例形式图文并茂给出了说明。

WindowLevel

那不是不是新创建的UIWindow一定会覆盖在界面的最上面呢?其实并不是这样的。UIWindow有一个类型为“UIWindowLevel”的属性,该属性定义了UIWindow的层级,系统定义的WindowLevel一共有三种取值,如下所示:


1

2

3


UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal;

UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert;

UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar;

把这几个值打印出来,得到结果如下:


1

2

3


UIWindowLevelNormal=0.000000

UIWindowLevelAlert=2000.000000

UIWindowLevelStatusBar=1000.000000

从中能够看出,默认程序的UIWindow的层级是UIWindowLevelNormal,当系统需要覆盖在其上覆盖UIAlertView时,就会创建一个层级是UIWindowLevelAlert的UIWindow,因为其WindowLevel值更高,所以就覆盖在上面了。

手工创建UIWindow

有些时候,我们也希望在应用开发中,将某些界面覆盖在所有界面的最上层。这个时候,我们就可以手工创建一个新的UIWindow。需要注意的是,和创建UIView不同,UIWindow一旦被创建,它就自动地被添加到整个界面上了。

还有一点需要注意的是,如果我们创建的UIWindow需要处理键盘事件,那就需要合理地将其设置为keyWindow。keyWindow是被系统设计用来接收键盘和其他非触摸事件的UIWindow。我们可以通过makeKeyWindow和resignKeyWindow方法设置UIWindow实例的keyWindow与否。

P.S:在实际开发中发现,为了让UIWindow实例可见,一般需要调用makeKeyAndVisible方法,否则UIWindow实例没能正常呈现出来,简而言之,管理UIWindow的visible的方法除了makeKeyAndVisible之外没有找到类似于makeVisible的方法;因此不禁对和创建UIView不同,UIWindow一旦被创建,它就自动地被添加到整个界面上了这句话产生了怀疑…其实不用怀疑,控制UIWindow的visible与否的相关属性和其他UIView的属性一样,是hidden。所以,在不调用makeKeyAndVisible的情况下,UIWindow实例没能正常显示的原因是因为Window的hidden默认值为true,所以设置其为false就好了。

那么在哪些场合会涉及到“手工创建UIWindow”呢?参考唐巧在《iOS开发进阶》里的描述,我认为支付宝钱包等App的密码保护页面是基于UIWindow实现的,当用户从应用的任何界面按Home键退出,过一段时间再从后台切换回来时,显示一个密码输入界面。只有用户输入了正确的密码,才能进入退出前的界面。因为这个密码输入界面可能从任何应用界面弹出,并且需要盖住所有界面的最上层,所以很合适做一个UIWindow来实现。

P.S:我想至少有另外一个替换方案,这个方案不需要创建一个Window,具体的策略是:1. 找到当前Window;2. 找到当前ViewController;3. 在当前ViewController中以modal形式呈现一个新View Controller;更详细的介绍这里里有描述。

除了类似于支付宝钱包App的手势解锁功能界面之外,其他适合用UIWindow来实现的功能还包括:应用的启动介绍页,应用内的通知提醒消息,应用内的弹出框广告等。

仿微信ActionSheet

笔者总觉得iOS原生的ActionSheet比较丑,如下:

iOS原生的ActionSheet除了能对button titles进行定义之外,不能进行更多其他的设置。

相较而言,微信自定义的ActionSheet漂亮得多,恰好通过唐巧大神的《iOS开发进阶》学习到了UIWindow的相关内容,所以决定使用UIWindow实现一个类似于微信的ActionSheet,最终效果如下:

Demo代码详见这里

时间: 2024-08-22 16:55:08

UIWindow学习的相关文章

UIwindow的学习

UIwindow 的学习 层级关系测试代码: @interface AppDelegate () @property (nonatomic, strong) UIWindow *arlewWindow; @property (nonatomic, strong) UIWindow *norWindow; @property (nonatomic, strong) UIWindow *statusWindow; @end - (BOOL)application:(UIApplication *)a

UIView 和 UIWindow 的学习内容

UIWindow是UIView的子类,一个程序只能有一个window主窗口. 在XCode7之后我们创建UIWindow的对象,代码如下: //创建一个窗口,使其铺满屏幕(设置大小)          初始化的时候不要用self.window,这样相当于先调用setter方法再申请空间,可能会出现传值错误 _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; //UIScreen mainScreen代表

iOS 开发学习之 User Interface(2)UIWindow 视窗

UIWindow 视窗 a. 所有的UI直接或间接的放在UIWindow之上. b. UIWindow 继承自UIView. c. 视窗的创建:初始化视窗对象,指定其尺寸,以主屏幕([UIScreen mainScreen])范围指定. d. 将视窗设置为主窗口并使其可见 [window makeKeyAndVisible]; 一个应用程序只有一个主窗口. /* AppDelegate.m - (BOOL)application:(UIApplication *)application didF

iOS UIWindow 与 windowLevel 学习

Pop几个关键点 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" 会使对象主窗口展示在最前端  makeKeyAndVisible  方法使 对象window成为了 KeyWindow  但是如果 keyW

【学习总结】IOS程序运行过程 、UIWindow 、controller 、 UIView 创建过程的总结

程序启动开始到view显示: 程序启动首先会执行main函数 - > UIApplicationMain函数: 程序启动 (加载框架,info文件,资源等) 执行Main函数 初始化UIApplication单例对象 初始化AppDelegate对象,并设为UIApplication对象的代理 然后调用UIApplication的didFinishLaunchingWithOptions方法创建UIWindow对象,设置rootViewController根控制器等 然后建立一个主事件循环,其中

UIWindow全部API学习。

写API的目的在于作为一个字典的作用.简单,明了,温习,复习. //1.定义一个CGFloat类型的UIWindowLevel,UIWindowLevel分为三种不同选择,定义了UIWindow不同层级的展示方式,UIWindow在现实的时候会根据三种不同选择进行不同的排序,即level高的将排在level比他低的层级前面. typedef CGFloat UIWindowLevel; //2.添加UIScreen屏幕属性 @property(nonatomic,retain) UIScreen

iOS开发-UI (一)补充 UIWindow UIView UIlabel

之前忘了把这些整理出来,现在补充一下,应该放在前面学习的 知识点: 1.UI的初步认识 2.UIWindow 3.UIView 4.UIlabel ======================== UI的初步认识 1.什么是UI(*) UI即User Interface(用户界面)的简称.UI设计则是指对软 件的人机交互.操作逻辑.界面美观的整体设计.好的UI设 计不仅是让软件变得有个性有品味,还要让软件的操作变得 舒适.简单.自由.充分体现软件的定位和特点. 2.第一个UI工程 1)UI工程的

UIWindow ,UIlable

1.创建window 1 //1.创建window,UIScreen是屏幕类,创建和屏幕等大的窗口 2 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 3 //2.背景颜色 4 //self.window.backgroundColor = [UIColor greenColor]; 9 10 self.window.backgroundColor = [UIColor whiteColor

IOS学习笔记 -- Modal和Quartz2D

一. Modal1.Modal的默认效果:新控制器从屏幕的最底部往上钻,直到盖住之前的控制器为止;Modal只是改变了View的现实,没有改变rootViewController 2.常用方法1>.以Modal的形式展示控制器- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion2>.关