Swift 3:保留当前ViewController,销毁此前所有ViewController(非导航控制器)
嘿,刚好碰到过类似的场景!不用导航控制器,还要保住当前显示的ViewController、干掉之前所有的,这两个方案应该能帮到你:
方案1:重置UIWindow的根视图控制器
这是最直接的方法——把当前显示的ViewController设为窗口的根VC,这样之前的所有VC因为失去了强引用,会被系统自动销毁。
先拿到当前活跃的VC(不管它是根VC本身,还是被present出来的),然后替换根VC:
// 获取当前显示的ViewController(适配iOS13+多场景) guard let currentVC = UIApplication.shared.connectedScenes .filter({ $0.activationState == .foregroundActive }) .first(where: { $0 is UIWindowScene }) .flatMap({ $0 as? UIWindowScene })?.windows .first(where: { $0.isKeyWindow })?.rootViewController?.presentedViewController ?? UIApplication.shared.connectedScenes .filter({ $0.activationState == .foregroundActive }) .first(where: { $0 is UIWindowScene }) .flatMap({ $0 as? UIWindowScene })?.windows .first(where: { $0.isKeyWindow })?.rootViewController else { return } // 设为新的根VC,切断旧的引用链 UIApplication.shared.connectedScenes .filter({ $0.activationState == .foregroundActive }) .first(where: { $0 is UIWindowScene }) .flatMap({ $0 as? UIWindowScene })?.windows .first(where: { $0.isKeyWindow })?.rootViewController = currentVC
注:如果只支持iOS13以下版本,可以简化成直接用UIApplication.shared.keyWindow获取窗口
方案2:手动清理Present链
如果你的VC是通过present方式一层层弹出的,可以让当前VC直接被最底层的VC重新present,跳过中间的所有VC,这样中间的VC会被释放:
// 从当前VC往上找,直到找到最顶层的presenting VC(最初的根VC) var topPresentingVC = currentVC.presentingViewController while let nextPresentingVC = topPresentingVC?.presentingViewController { topPresentingVC = nextPresentingVC } // 先dismiss当前VC,再让最底层VC重新present它(关闭动画更自然) currentVC.dismiss(animated: false) { topPresentingVC?.present(currentVC, animated: false, completion: nil) }
这个方案适合需要保留底层根VC,但只想清除中间弹出VC的场景。
额外提醒
- 不管用哪个方案,都要检查当前VC有没有被其他对象强引用(比如单例、全局变量),不然之前的VC可能无法被正确销毁。
- 如果用了容器类VC(比如UITabBarController),要先拿到选中的子VC再进行后续操作。
内容的提问来源于stack exchange,提问作者Will Cohen
相关产品推荐
相关产品推荐

