iOS Swift导航时当前ViewController异常变更及半透明弹窗问题咨询
解决模态跳转时保留原页面作为背景且避免Tab页崩溃的问题
我来帮你搞定这个问题!你遇到的核心问题其实是不同模态呈现样式的视图层级处理逻辑不一样,咱们一步步来解决:
为什么你的现有方案有问题?
- 用
.fullScreen时:系统会把原ViewController的视图从视图层级中彻底移除,所以哪怕你把新页面的Alpha调得再低,也看不到原页面——因为它已经不在屏幕上了。 - 用
.popover时:虽然能保留原视图,但popover的呈现逻辑在TabBarController环境下很容易因为布局约束、锚点设置不当或者层级冲突导致崩溃,确实不适合在Tab页面里用。
最简单的解决方案:用.overFullScreen替代.fullScreen
这个样式完美适配你的需求:它会让新页面覆盖在原页面之上,不会移除原视图,所以只要给新页面设置透明背景/Alpha值,就能看到原页面,而且在Tab页面里也不会崩溃。
修改你的代码如下:
let visitorModalVc = UIStoryboard(name: "VisitorInfo", bundle: nil).instantiateViewController(withIdentifier: "visitor_modal_vc") as! VisitorInfoModalViewController // 替换成overFullScreen,保留原页面视图 visitorModalVc.modalPresentationStyle = .overFullScreen // 设置新页面的背景为半透明(推荐用背景色带Alpha,避免影响子视图) visitorModalVc.view.backgroundColor = UIColor.white.withAlphaComponent(0.8) // 如果需要整个页面半透明,也可以直接设置view.alpha,但会影响所有子视图 // visitorModalVc.view.alpha = 0.8 self.present(visitorModalVc, animated: true, completion: nil)
进阶:自定义弹窗样式(非全屏)
如果你的需求不是全屏弹窗,而是想要自定义大小的弹窗,同时保留原页面背景,可以用自定义UIPresentationController来实现,这样在Tab页面也能稳定运行:
1. 创建自定义PresentationController
class CustomPresentationController: UIPresentationController { // 设置弹窗的位置和大小,这里例子是居中的300x400弹窗 override var frameOfPresentedViewInContainerView: CGRect { guard let containerBounds = containerView?.bounds else { return .zero } let popWidth: CGFloat = 300 let popHeight: CGFloat = 400 let originX = (containerBounds.width - popWidth) / 2 let originY = (containerBounds.height - popHeight) / 2 return CGRect(x: originX, y: originY, width: popWidth, height: popHeight) } override func containerViewWillLayoutSubviews() { super.containerViewWillLayoutSubviews() // 给弹窗设置布局 presentedView?.frame = frameOfPresentedViewInContainerView // 可选:添加半透明遮罩层,增强视觉层次 let dimmingView = UIView(frame: containerView?.bounds ?? .zero) dimmingView.backgroundColor = UIColor.black.withAlphaComponent(0.3) containerView?.insertSubview(dimmingView, at: 0) } }
2. 在目标ViewController中配置自定义呈现
class VisitorInfoModalViewController: UIViewController { // 指定使用自定义呈现样式 override var modalPresentationStyle: UIModalPresentationStyle { get { .custom } set {} } // 返回自定义的PresentationController override var presentationController: UIPresentationController? { return CustomPresentationController(presentedViewController: self, presenting: presentingViewController) } // 你的其他业务代码... }
3. 正常呈现即可
let visitorModalVc = UIStoryboard(name: "VisitorInfo", bundle: nil).instantiateViewController(withIdentifier: "visitor_modal_vc") as! VisitorInfoModalViewController self.present(visitorModalVc, animated: true, completion: nil)
这样既保留了原页面作为背景,又能实现自定义的弹窗样式,而且在TabBarController中也不会出现崩溃问题。
内容的提问来源于stack exchange,提问作者A J
相关产品推荐
相关产品推荐

