开发的时候我们经常遇到这样的场景,就是在当前视图界面上添加一个黑色透明的蒙版。一般我们就是新建一个蒙版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之前的方法栈,
发现window调用了dealloc,因为我们蒙版的父视图keyWindow dealloc释放掉了,所以我们的蒙版就消失了
4.解释了蒙版的消失,但当前的window怎么dealloc呢?我的界面明明还正常显示呢。
5.猜测是不能当前显示蒙版的keyWindow和我们显示主界面的keyWindow不一样导致的,但为啥会不一致呢,之前这样把蒙版直接加在keyWindow上都没关系,难道和在alertView回调显示有关系。
6.做了上面大胆的假设,开始一步步调试,
a.在alertVeiw弹框弹出之前打印keyWindow的值
(lldb) po [UIApplication sharedApplication].keyWindow
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通过上面的打印,我们可以清楚的看到。在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.遇到问题,才能更好的提升,多做总结。