美文网首页iOS 坑的集中营iOS DeveloperIOS
创建的UIWindow为什么不显示

创建的UIWindow为什么不显示

作者: 踩坑小分队 | 来源:发表于2016-10-14 10:19 被阅读2205次

创建了一个window却不显示,怎么个情况。
相关代码如下:
创建一个按钮,通过按钮的单击事件来创建window,创建的window是不需要添加到相关的控件的,只要创建就会添加到界面上。
1、但是这里也创建window了,怎么没有显示?

- (void)test2
{
    UIWindow *myWindow3 = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    myWindow3.backgroundColor = [UIColor greenColor];
    myWindow3.windowLevel = 100;
    myWindow3.hidden = NO;
    [myWindow3 makeKeyWindow];
    
    NSLog(@"1当前所有的window %@",[UIApplication sharedApplication].windows);
}

2、但是将window设置成员变量就能够如期的看到window,代码如下

@interface ViewController ()
@property(nonatomic,strong)UIWindow *myWindow1;
@end

通过按钮响应事件调用test1方法,会发现创建的window显示出来了

// 将window设置成全局变量
- (void)test1
{
    self.myWindow1 = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.myWindow1.backgroundColor = [UIColor redColor];
    self.myWindow1.windowLevel = -1;
    self.myWindow1.hidden = NO;
}

也就是说window必须要设置成成员变量才能被显示出来吗?为什么?继续进行以下相关的测试:
3、没有声明成成员变量,单独创建的window类,直接调用没有显示

// 单独创建UIWindow类
- (void)test3
{
    MyWindow1 *myWindow = [[MyWindow1 alloc] initWithFrame:[UIScreen mainScreen].bounds];
    myWindow.backgroundColor = [UIColor greenColor];
    myWindow.windowLevel = 100;
    myWindow.hidden = NO;
    [myWindow makeKeyWindow];
}

4、单独创建UIWindow类,然后设置成全局变量,创建window之后有window显示

@interface ViewController ()
@property(nonatomic,strong)MyWindow1 *myWindow;
@end
- (void)test4
{
    self.myWindow = [[MyWindow1 alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.myWindow.backgroundColor = [UIColor greenColor];
    self.myWindow.windowLevel = 100;
    self.myWindow.hidden = NO;
    [self.myWindow makeKeyWindow];
}

5、创建单例window

+ (ShowWindow *)shareShowWindow
{
    static ShowWindow *window = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (window == nil) {
            window = [[ShowWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        }
    });
    
    return window;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor redColor];
        // 在window上面添加相关控件
        UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeSystem];
        tempBtn.frame = CGRectMake(100, 200, 100, 100);
        [tempBtn setTitle:@"点我消失" forState:UIControlStateNormal];
        tempBtn.backgroundColor = [UIColor greenColor];
        [tempBtn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:tempBtn];
    }
    return self;
}

- (void)clickBtn:(UIButton *)sender
{
    self.hidden = YES;
}

- (void)show
{
    [self makeKeyWindow];
    self.hidden = NO;
}

在ViewController中调用,创建的window显示了

// 创建window的单例进行实验
- (void)test5
{
    ShowWindow *window = [ShowWindow shareShowWindow];
    [window show];
}

总结:通过以上的实验可以总结出,并不是只有成员变量才可以,单例也可以,他们的共同点就是生命周期足够长。
这个时候产生一个疑问,单独创建的一个局部变量的button,添加在view上面怎么能够显示?UIWindow的父类虽然也是UIView,但是UIWindow的显示方式和view不一样。一般的view创建完了是需要添加到父控件上面的,对,就是这个"添加",父控件强引用了button,也就是button的引用计数+1了。
刚刚上面也说了,"创建的window是不需要添加到相关的控件的,只要创建就会添加到界面上",window并没有添加到任何的地方。
那么创建完了window可以找到吗?当然可以。通过以下代码可以找到创建的window。

NSLog(@"2当前所有的window %@",[UIApplication sharedApplication].windows);

我测试的时候也是这么观察的

- (void)clickBtn:(UIButton *)sender
{
    // 为了观察是不是新创建的window被当前的window挡住了
    AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
    app.window.alpha = 0.3;
    
    // 可以显示创建的window
    [self test1];
    
    // 不能正常显示创建的window
//    [self test2];
    
    // 不能正常的显示创建的window
//    [self test3];
    
    // 可以正常的显示创建的window
//    [self test4];
    
    // 可以正常显示创建的window
//    [self test5];
    
    NSLog(@"2当前所有的window %@",[UIApplication sharedApplication].windows);
}

在以上的实验中不同的方式添加window,添加完毕之后就可以查看windows中的情况了。
比如调用完了test1,打印[UIApplication sharedApplication].windows就会发现多一个window,并且可以和test1创建的window比较一下,确认是一个window。调用完test3,会发现没有添加新的window。
相关的Demo可以参考:https://github.com/RunOfTheSnail/UIWindowDemo

这是为什么?难道创建完了window没有被添加进[UIApplication sharedApplication].windows中吗?猜想,没有被添加进去,新创建的window没有被[UIApplication sharedApplication].windows强引用,很可能仅仅是弱引用。
做如下实验:
还是通过按钮的点击事件调用的。

// 测试创建的window和[UIApplication sharedApplication].windows的关系
- (void)test6
{
    self.myWindow2 = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.myWindow2.backgroundColor = [UIColor greenColor];
    self.myWindow2.windowLevel = 100;
    self.myWindow2.hidden = NO;
    [self.myWindow2 makeKeyWindow];
    NSLog(@"查看1   %@",[UIApplication sharedApplication].windows);
    self.myWindow2 = nil;
    NSLog(@"查看2   %@",[UIApplication sharedApplication].windows);
}

打印结果如下:这个和想要的结果不一样,想要的结果是第一次打印两个window,第二次打印一个window,有点演砸了。。。。。。。。

2016-10-14 10:06:57.459 UIWindowDemo[83896:1915917] 查看1   (
    "<UIWindow: 0x7fef83713620; frame = (0 0; 375 667); alpha = 0.3; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fef83714b40>; layer = <UIWindowLayer: 0x7fef83710f80>>",
    "<UIWindow: 0x7fef85010e30; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x7fef850122a0>; layer = <UIWindowLayer: 0x7fef85010570>>"
)
2016-10-14 10:06:57.460 UIWindowDemo[83896:1915917] 查看2   (
    "<UIWindow: 0x7fef83713620; frame = (0 0; 375 667); alpha = 0.3; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fef83714b40>; layer = <UIWindowLayer: 0x7fef83710f80>>",
    "<UIWindow: 0x7fef85010e30; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x7fef850122a0>; layer = <UIWindowLayer: 0x7fef85010570>>"
)

但是得考虑一个问题。短时间window可能会不释放的问题,进行再一次的实验
创建另外一个测试按钮,通过点击事件来查看windows中的情况

 // 这个是配合着test6来测试的,查看windows数组的情况
    UIButton *myTempBtn = [UIButton buttonWithType:UIButtonTypeSystem];
    [myTempBtn setTitle:@"再点我,测试test2" forState:UIControlStateNormal];
    myTempBtn.frame = CGRectMake(100, 300, 300, 100);
    myTempBtn.backgroundColor = [UIColor greenColor];
    [myTempBtn addTarget:self action:@selector(clickMyTempBtn:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:myTempBtn];
- (void)clickMyTempBtn:(UIButton *)sender
{
    NSLog(@"查看3 %@",[UIApplication sharedApplication].windows);
}
 查看3 (
    "<UIWindow: 0x7faa09439ec0; frame = (0 0; 375 667); alpha = 0.3; autoresize = W+H; gestureRecognizers = <NSArray: 0x7faa0943af80>; layer = <UIWindowLayer: 0x7faa094369e0>>"

运行完test6之后,查看1和查看2打印的结果都是两个window,点击测试按钮之后,再次测试发现打印的是一个window,这下放心了。验证了自己的猜想。

总结:
1、创建的window不需要添加到任何的控件上就能显示,显示的规律是通过windowLevel的等级来显示的,相关参考:http://www.jianshu.com/p/f60471a7d935
2、新创建的window没有被[UIApplication sharedApplication].windows强引用,只是能通过[UIApplication sharedApplication].windows找到创建的window。所以想要创建的window显示,那就必须保证其生命周期。

以上是我自己根据相关的运行效果总结的,如果有哪位大神觉得有地方描述的不准确,欢迎指正哈,在下感激不尽!!!

相关文章

  • 创建的UIWindow为什么不显示

    创建了一个window却不显示,怎么个情况。相关代码如下:创建一个按钮,通过按钮的单击事件来创建window,创建...

  • UIWindow

    1、UIWindow 创建了显示不出来 UIWindow要创建成全局变量,不然刚创建对象就会被销毁,导致windo...

  • iOS --- UI 简单总结

    代码创建UIWindow对象 Xcode7之后使用代码创建UIWindow对象: //创建UIWindow对象 s...

  • UIWindow的使用,以及需要注意的坑

    自定义创建Window UIWindow是UIView的子类,UIView对象是通过方法addSubview:显示...

  • UIWindow

    目录:1、UIWindow简介2、UIWindow的创建3、获取UIWindow 1、UIWindow简介 UIW...

  • UIWindow的显示问题

    今天创建UIWindow的时候,显示不出来。要把window变成实例变量或者属性变量才能显示出来。 { UIW...

  • UIWindow的特别注意

    1.新创建的UIWindow不需要添加到任何父控件上就能显示出来(需保证创建的window不销毁,用属性强引用)2...

  • UIWindow显示到屏幕最上层

    自己创建一个UIWindow了,并把keyWindow复制给他,却显示不到屏幕最前边,[window makeKe...

  • UIWindow的显示

    UIWindow的显示 强引用window, window.hidden = false, 则window就会展示出来

  • iOS—UIWindow与UIView

    一、UIWindow1、什么是UIWindow 管理和协调应用程序的显示。UIWindow类是UIView的子类,...

网友评论

  • MemoryReload:你的第一次置空``self.myWindow2 = nil;``之所以会失败,是因为self.myWindow2所指的对象在自动释放池里,如果你换用手动管理内存编写代码,明确的release掉,应该打印的windows数组就会是只有一个window了。:relieved:
  • 5a2d9796d92a:同样遇到了问题,已经解决,最后的总结就是window在创建完毕后,如果不是局部变量的话,就直接释放掉了,所以没有显示
    踩坑小分队:@莪笨善良 局部变量被释放了

本文标题:创建的UIWindow为什么不显示

本文链接:https://www.haomeiwen.com/subject/ikowyttx.html