【iOS】修改根控制器后,view的叠加在窗口的问题

2020-03-28 20:59:45 浏览数 (1)

问题描述

笔者在App登录后,切换RootViewController时,发现window上盖着一层看不见的View。如图所示:

然后看了window的层级,如图所示:

发现window除了有一个根控制器TabbarController,还有一个UILayoutContainerView,不难分析出,这就是之前旧的RootVC残留下来,没有释放的View。

解决方法

一开始以循环引用的角度入手,但是无奈项目过于庞大,找了非常久仍无法解决问题。最后只好从网上寻求解决方式,最后找到了跟我遇到一样问题的一篇,文章,链接如下: http://openfibers.github.io/blog/2015/12/15/window-setrootviewcontroller-view-not-removed-hack/

文中的解决如下:

代码语言:javascript复制
//hack of setRootViewController: old rootViewController's view never removed from window
- (void)setRootViewController:(UIViewController *)rootViewController
{
    //remove old rootViewController's sub views
    for (UIView* subView in self.rootViewController.view.subviews)
    {
        [subView removeFromSuperview];
    }

    //remove old rootViewController's view
    [self.rootViewController.view removeFromSuperview];

    //set new rootViewController
    [super setRootViewController:rootViewController];

    //remove empty UILayoutContainerView(s) remaining on root window
    for (UIView *subView in self.subviews)
    {
        if (subView.subviews.count == 0)
        {
            [subView removeFromSuperview];
        }
    }
}

由于项目是用swift编写的,然后兴冲冲的将以上代码翻译成swift语言,发现怎样都不能满足 subView.subviews.count == 0 。经过打印子view的层级结构,发现UILayoutContainerView仍残余 UITransitionView,那么这个就是 subView.subviews.count == 0 不满足的原因。因此,我们只要耐心等专场动画结束后,再去判断 subView.subviews.count == 0即可。修改后的代码如下:

代码语言:javascript复制
class MPWindow: UIWindow {
    override var rootViewController: UIViewController? {
        willSet {
            guard let old = rootViewController else {
                return
            }
            for sub in old.view.subviews {
                sub.removeFromSuperview()
            }
            old.view.removeFromSuperview()
        }
        didSet {
            // 延迟2s判断
           DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()   Double((Int64)(2 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { () -> Void in
                for v in self.subviews {
                    if v.subviews.count == 0 {
                        v.removeFromSuperview()
                    }
                }
            }
        }
    }
}

0 人点赞