你的位置:首页 > 操作系统

[操作系统]你真的了解UIWindow吗?


一:首先查看一下关于UIWindow的定义

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIWindow : UIView//window的屏幕,默认是 [UIScreen mainScreen] ,不能更改,否则没有界面@property(nonatomic,strong) UIScreen *screen NS_AVAILABLE_IOS(3_2); //window的视图层级,默认是0.0@property(nonatomic) UIWindowLevel windowLevel;      //是否是keyWindow@property(nonatomic,readonly,getter=isKeyWindow) BOOL keyWindow;//该方法不应该被手动调用,当window变为keyWindow时会被自动调用来通知window。可以继承UIWindow重写此方法来实现功能- (void)becomeKeyWindow;  // 该方法不应该被手动调用,当window不再是keyWindow时(例如其他window实例调用了- makeKeyWindow或- makeKeyAndVisible方法)会被自动调用来通知window。可以继承UIWindow重写此方法来实现功能。             - (void)resignKeyWindow;               //该方法使window变为keyWindow,但不影响显示状态- (void)makeKeyWindow;//显示主window并将window设为key并显示,该方法让window显示并变为keyWindow。调用该方法会让window排在其level组中的最上面。如果只想改变window的显示而不影响keyWindow状态,可以直接设置window的hidden属性为NO。- (void)makeKeyAndVisible;              //根控制器@property(nullable, nonatomic,strong) UIViewController *rootViewController NS_AVAILABLE_IOS(4_0); //UIApplication调用window的该方法给window分发事件,window再将事件分发到合适的目标,比如将触摸事件分发到真正触摸的view上。可以直接调用该方法分发自定义事件。- (void)sendEvent:(UIEvent *)event;          // 把该window中的一个坐标转换成在目标window中时的坐标值- (CGPoint)convertPoint:(CGPoint)point toWindow:(nullable UIWindow *)window;  // 把目标window中的一个坐标转换成在该window中时的坐标值- (CGPoint)convertPoint:(CGPoint)point fromWindow:(nullable UIWindow *)window; // 把该window中的一个矩阵转换成在目标window中时的矩阵值- (CGRect)convertRect:(CGRect)rect toWindow:(nullable UIWindow *)window;// 把目标window中的一个矩阵转换成在该window中时的矩阵值- (CGRect)convertRect:(CGRect)rect fromWindow:(nullable UIWindow *)window;@end

UIWindow是一种特殊的UIView,通常在一个app中至少会有一个UIWindow。iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的View,最后将控制器的View添加到UIWindow上,于是控制器的View就显示在屏幕上了。一个iOS程序之所以能显示在屏幕上,完全是因为它有UIWindow,也就是说,没有UIWindow就看不到任何UI界面。状态栏和键盘都是特殊的UIWindow;UIWindow还是事件处理的重要组成部分,当应用最初收到事件时,会派发给合适的UIWindow对象,再由其传递到合适的UIView对象。同时,window和view controller对象一起工作还可以实现界面旋转等其他控制操作。

知识点1:UIWindowLevel常量值 设置UIWindow的等级

UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal; //默认,值为0UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert; //值为2000 UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar ; // 值为1000

该属性表示了window在屏幕z轴方向上的位置,系统提供了UIWindowLevel的三个常量值,显示应用内容的main window默认设置为UIWindowLevelNormal,即最低的level。其他一些界面元素比如status bar和alert view会使用相应的level。windowLevel也可以设置为其他的任意数值,比如系统键盘所在的window,其windowLevel总是比调用键盘的window的level大1,选中输入内容时的拷贝,粘贴等选项所在的window其windowLevel是2100。可以多个window设置为同一个windowLevel,在这些window中,最后调用显示方法的window排在上面。不同level的window组中,总是更高level的window在低level的window的上面。

知识点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:代码来创建window初始化界面

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  myViewController = [[MyViewController alloc] init];  window.rootViewController = myViewController;  [window makeKeyAndVisible];  return YES;}

知识点4:在有storyboard的项目中,UIWindow是如何创建的?

当用户点击应用程序图标的时候,先执行Main函数,执行UIApplicationMain(),根据其第三个和第四个参数创建Application,创建代理,并且把代理设置给application(看项目配置文件info.plist里面的storyboard的name,根据这个name找到对应的storyboard),开启一个事件循环,当程序加载完毕,他会调用代理的didFinishLaunchingWithOptions:方法。在调用didFinishLaunchingWithOptions:方法之前,会加载storyboard,在加载的时候创建一个window,接下来会创建箭头所指向的控制器,把该控制器设置为UIWindow的根控制器,接下来再将window显示出来,即看到了运行后显示的界面。

知点点5:获取UIwindow

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

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

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

3:view.window获得某个UIView所在的UIWindow。