iOS使用[UIApplication sharedApplication].keyWindow添加子视图的问题

      开发的时候我们经常遇到这样的场景,就是在当前视图界面上添加一个黑色透明的蒙版。一般我们就是新建一个蒙版view,然后加在当前显示的window上。如下:

1-1代码

    UIWindow *window = [UIApplication sharedApplication].keyWindow;//注:keyWindow当前显示界面的window
    UIView *subView = [[CView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    subView.backgroundColor = [UIColor blackColor];
    subView.alpha = 0.5;
    [window addSubview:subView];

一般我们就是在keyWindow上直接添加这种蒙版的view,小编也不例外。但今天确遇到了一个诡异的问题,就是由于使用这个keyWindow造成的。

下面简单交代下问题背景:

项目中有这样的场景,就是点击某一按钮之后,会优先弹出一个系统的UIAlertView的弹框,然后会在alertView的点击代理的回调

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

里面调用显示蒙版的方法(方法的实现和上面1-1代码类似)。然后就出现了奇怪的问题,我添加在keyWindow上的蒙版加上去之后瞬间消失了。

分析问题:

1.看到蒙版自己消失了第一反应想到应该会走自定义蒙版View的dealloc方法,于是就在dealloc方法那打了一个断点。

2.果然走到我们的蒙版view dealloc方法被调用了,但我又没有自己掉dimiss和remvoe方法,怎么会dealloc的。

3.分析调用dealloc之前的方法栈,

iOS使用[UIApplication sharedApplication].keyWindow添加子视图的问题_第1张图片

发现window调用了dealloc,因为我们蒙版的父视图keyWindow dealloc释放掉了,所以我们的蒙版就消失了

4.解释了蒙版的消失,但当前的window怎么dealloc呢?我的界面明明还正常显示呢。

5.猜测是不能当前显示蒙版的keyWindow和我们显示主界面的keyWindow不一样导致的,但为啥会不一致呢,之前这样把蒙版直接加在keyWindow上都没关系,难道和在alertView回调显示有关系。

6.做了上面大胆的假设,开始一步步调试,

a.在alertVeiw弹框弹出之前打印keyWindow的值
(lldb) po [UIApplication sharedApplication].keyWindow
; layer = >

b.在alertView的代理方法- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex里打印keyWindow的值
po [UIApplication sharedApplication].keyWindow
<_UIAlertControllerShimPresenterWindow: 0x7fa48c613ad0; frame = (0 0; 414 736); opaque = NO; autoresize = W+H; 

c.在alertView的代理方法- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex alertView消失之后再打印

(lldb) po [UIApplication sharedApplication].keyWindow
; layer = >

通过上面的打印,我们可以清楚的看到。在alertView弹出之后的keyWindow和我们弹出之前消失之后的keyWindow是不一样的。地址和对象都不同一个

UIWindow: 0x7fa48c611c00 和 _UIAlertControllerShimPresenterWindow: 0x7fa48c613ad0

这就解释了为啥我们弹出的视图出现后就消失了,因为当alertVeiw弹出的时候的当前的keyWidow已经是_UIAlertControllerShimPresenterWindow对象了,alertView消失之后,这个window就释放了,所以加在上面的蒙版就消失了。


解决方法:

1.我们看到在UIAlertView另一个回调里- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex UIAlertView dismiss之后的keyWindow和我们是一样的,可以在这里使用[UIApplication sharedApplication].keyWindow方式去加视图。

2.不适用[UIApplication sharedApplication].keyWindow这种方式,[[UIApplication sharedApplication] delegate].window 或

     [[UIApplication sharedApplication].windows objectAtIndex:0]这两种方式,这样获取的window不是当前的keyWindow,而是主window。


总结分析:

1.使用UIAlertView的时候,无论是自己写还是封装给别人使用的时候,最好都

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex 这个回调,因为这是alertView已经完全消失。

2.我们不可避免的会遇到问题,我们平常习以为常的东西,有些场景也会遇到一些特殊的问题,我们要保持警惕。

3.遇到问题,才能更好的提升,多做总结。





你可能感兴趣的:(iOS开发)