自定义创建Window
UIWindow是UIView的子类,UIView对象是通过方法addSubview:显示到父视图,但是window却不需要这样就能显示,只需要设置hidden为NO即可,实际中一个window对象真正显示到屏幕上还受到windowLevel影响
self.window1 = [[UIWindow alloc] initWithFrame:CGRectMake(0, 400, 150, 150)];
UIViewController *vc1 = [[UIViewController alloc] init];
vc1.view.backgroundColor = [UIColor redColor];
self.window1.rootViewController = vc1;
self.window1.windowLevel = 9;
[self.window1 makeKeyAndVisible];
- 注意: [window makeKeyWindow];
window.hidden = NO;
等价与
[self.window2 makeKeyAndVisible];
一个屏幕可以显示几个window?
理论上个数不限制,按需显示。屏幕顶部的状态栏、alert弹窗、键盘都是常见的window。
与window相关的几个知识点
1. windowLevel属性
默认值0.0,即系统定义的UIWindowLevelNormal。系统总共定义三种level,即如下
UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal = 0.f;
UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert = 2000.f;
UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar API_UNAVAILABLE(tvos) = 1000.f;
level越高在屏幕上显示层级越靠前,如果多个window设置相同的level,这时显示的层级就和设置hidden=NO的顺序有关,最后设置的会显示在最上层。
2. keyWindow
实际开发中我们常常会把一些显示级别高或者全局显示的视图放到keyWindow,通过[UIApplication sharedApplication].keyWindow获取使用。那keyWindow是什么,和其他window有什么不同?keyWindow即主窗口,参考官方文档说明,在程序运行期间只会存在一个主窗口,而且主窗口可以接收键盘事件及非触摸事件。接收键盘事件好理解,什么是非触摸事件呢?原文有相关描述
Whereas touch events are delivered to the window in which the touch occurred, events that don’t have an associated coordinate value are delivered to the key window.
英文能力有限,姑且理解为触摸事件传递到当前触摸的window,同时会把这个触摸事件传递到主窗口,但这个触摸事件传递时不会带着与坐标系相关的值。这里非触摸即没有touch主窗口,但依然可以接收到触摸事件。
事实上任何window都可以设置为keyWindow,如果只是使用自定window展示alert信息或者toast信息,没有必要设置;如果alert里需要输入信息,那就必须设置。
设置keyWindow的方法有两个,即
- (void)makeKeyWindow;
- (void)makeKeyAndVisible;
UIApplication.sharedApplication.delegate.window和UIApplication.sharedApplication.keyWindow有什么区别?
- [UIApplication sharedApplication].keyWindow
是设备上当前正在显示的窗口。这通常是您应用程序的窗口,但也可能是系统窗口 - [UIApplication sharedApplication].delegate.window
是AppDelegate中定义的属性窗口,是主window;
@property (strong, nonatomic) UIWindow *window; - [UIApplication sharedApplication].windows.firstObject
等价于
[UIApplication sharedApplication].delegate.window - [UIApplication sharedApplication].windows.lastObject
- [[UIApplication sharedApplication]windows].lastObject
用来获取当前屏幕上最上层的一个UIWindow,但有可能不是当前的window
- (void)alertView {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:@"测试" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确认", nil];
[alertView show];
// UIWindow *window = [UIApplication sharedApplication].keyWindow; //是上面alert的window
UIWindow *window = [UIApplication sharedApplication].delegate.window;// 是AppDelegate中定义的属性窗口
UILabel *tempLabel =[[UILabel alloc]initWithFrame:CGRectMake(150, 150, 100, 20)];
tempLabel.font = [UIFont systemFontOfSize:16];
tempLabel.backgroundColor = [UIColor purpleColor];
tempLabel.text = @"测试window";
[window addSubview:tempLabel];
}
- 注意:UIWindow *window = [UIApplication sharedApplication].keyWindow,如果使用这个的时候,下面的tempLabel就会添加到UIAlertView所在的_UIAlertControllerShimPresenterWindow层,当alert消失的时候,对应的windows和tempLabel都会释放
总结:
https://developer.apple.com/documentation/uikit/uiwindow?language=objc
官方参考文档 - 《Multiple Display Programming Guide for iOS》Understanding Windows and Screens
网友评论