UIWindow

UIWindow 是什么?

官方定义:The UIWindow class defines an object known as a window that manages and coordinates the views an app displays on a device screen. Unless an app can display content on an external device screen, an app has only one window.

个人理解: UIWindow就是一种特殊的UIView, 管理和协调应用程序显示在屏幕上的所有Views。通常一个程序只会有一个UIWindow,但是也可以手动创建自己的UIWindow。UIWindow有两个重要的作用:第一,作为容器,包含应用程序所有的UIView;第二,分发触摸事件到Views中.

UIWindowLevel

一个Window一般都会有一个层级,比如UIWindow的默认级别是 UIWindowLevelNormal . UIWindow在显示的时候会根据UIWindowLevel级别进行排序的,Level高会显示在Level低的前面,比如UIAlertView, ios系统为了保证UIAlertView显示在所有界面之上,它会临时创建一个UIWindow,并设置更高层级的Level(UIWindowLevelAlert).

在ios系统中,枚举了三个Level:

UIWindowLevelNormal
UIWindowLevelStatusBar
UIWindowLevelAlert

如果你想创建一个window,需要显示在statusbar上面,但是又要在alertview下面,那么你可以指定window.windowLevel=UIWindowLevelStatusBar;如果你想创建一个window位于所有界面之上,你可以设置 window.windowLevel=UIWindowLevelAlert+1.

创建自己的UIWindow

有些时候,我们希望在我们的App中将某些页面放置在所有界面的最上面,这个时候,我们可以手动创建一个UIWindow。需要注意的是,和UIView不同,UIWindow一旦创建,就会被自动的添加到界面上,如设置window.hidden = NO,就会被自动显示出来(当然你的windowLevel足够高,否则有可能被别的界面遮挡住)

通过 [UIApplication sharedApplication].windows 可以获得当前应用的UIWindow列表。

windows: (
"<UIWindow: 0x7fd3fb544f10; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x7fd3fb564760>; layer = <UIWindowLayer: 0x7fd3fb542ec0>>",
"<UITextEffectsWindow: 0x7fd3fd120a60; frame = (0 0; 375 667); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x7fd3fd116770>>",
"<UIWindow: 0x7fd4008061b0; frame = (0 0; 375 667); autoresize = W+H; userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0x7fd400825a60>; layer = <UIWindowLayer: 0x7fd4005b01b0>>",
"<UIWindow: 0x7fd4000b9d80; frame = (0 20; 320 20); hidden = YES; userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0x7fd4000ba6f0>; layer = <UIWindowLayer: 0x7fd3fb6b7d20>>",
"<ATBaseWindow: 0x7fd40005b0f0; baseClass = UIWindow; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x7fd40006d460>; layer = <UIWindowLayer: 0x7fd40002ac00>>",
"<UIWindow: 0x7fd4006909a0; frame = (0 0; 375 667); hidden = YES; gestureRecognizers = <NSArray: 0x7fd4006914e0>; layer = <UIWindowLayer: 0x7fd3fd5b0ea0>>",
"<UIWindow: 0x7fd40004c1a0; frame = (255 0; 44 20); gestureRecognizers = <NSArray: 0x7fd3fb6af2a0>; layer = <UIWindowLayer: 0x7fd3fd457dc0>>"
)

创建一个UIWindow并显示到界面上(注意,尽量不要用局部变量创建UIWindow,不然会造成函数运行结束,UIWindow就会被释放掉)

// interface
@property (nonatomic, strong) UIWindow *myWindow;

// implementation
_myWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
_myWindow.backgroundColor = [UIColor redColor];
_myWindow.windowLevel = UIWindowLevelAlert;
_myWindow.hidden = NO;

个人比较喜欢采用这种方式创建UIWindow,因为这样创建的UIWindow不会占用keyWindow。如果不用了,直接置为nil即可。

if (_myWindow) {
    _myWindow.hidden = YES;
    [_myWindow resignKeyWindow];
    _myWindow = nil;
}

但是,也在ios7上发现了一个问题,如果用这种方式,在将window置为nil之后,发现其上面的View还有显示(上面的view也已经提前做了dismiss操作,虽然View还在显示,但事件的响应链已经没有了)。非常奇怪,有时候还会发现原来的界面收到了影响发生了闪动,位置错误等问题。暂且还没有发现具体原因,仅限ios7系统上发现的。如果谁知道具体原因,还望不吝赐教。

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

keyWindow被用来接收键盘或其它非触摸事件,在同一时刻只能有一个window为keywindow.

你可以调用 makeKeyAndVisible 或 makeKeyWindow 方法使一个UIWindow变成keyWindow。

真心不建议频繁使用keyWindow.因为在一个App中如果同时使用keyWindow,很容易出现界面错乱的问题。

当我们调用完 makeKeyWindow 或者 makeKeyAndVisible之后,我们自己的UIWindow就成为了keyWindow。然后,如何让自己的UIWindow由keyWindow变成非keyWindow呢?我们可以看下UIWindow的头文件,虽然有resignKeyWindow方法,但是此方法是不能直接调用的。虽然没有直接方法让我们的UIWindow变成非Window,但是我们可以通过其它方式实现。

方式1:

继承UIWindow,重载becomeKeyWindow方法,然后在这里设置appDelegate.window为keyWindow。这样操作,可以让我们的UIWindow很快变成非keyWindow,不会影响到他人使用keyWindow.

@implementation NoKeyWindow : UIWindow

- (void)becomeKeyWindow{
    [super becomeKeyWindow];
    [[[[UIApplication sharedApplication] delegate] window] makeKeyWindow];
}
@end

方式2:
监听UIWindowDidBecomeKeyNotification消息,判断自己的window是否变成keyWindow,如果是,则设置appDelegate.window为keyWindow.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowChange:) name:UIWindowDidBecomeKeyNotification object:nil];

- (void)windowChange:(NSNotification *)notification{
    if([notification.name isEqualToString:UIWindowDidBecomeKeyNotification] && notification.object == _loggoWindow){
        [[[[UIApplication sharedApplication] delegate] window]
        makeKeyWindow];
    }
}

引用文献

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值