You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UIKit:如何让UISheetPresentationController绑定当前页面,导航时隐藏

实现UISheetPresentationController与当前页面绑定的方案

核心思路

UISheetPresentationController是通过模态方式present在当前ViewController上的,默认会在导航push新页面时依然显示在顶层。要实现“与当前页面绑定、不干扰其他页面”的效果,核心是在当前页面离开导航栈顶部时隐藏sheet,返回时恢复显示状态。

具体实现步骤

1. 记录Sheet状态与引用

在当前ViewController中添加属性,用于跟踪sheet的显示状态和对应的ViewController引用:

class YourCurrentViewController: UIViewController {
    // 标记sheet是否处于显示状态
    private var isSheetPresented = false
    // 弱引用sheet的ViewController,避免内存泄漏
    private weak var sheetVC: UIViewController?
    
    // ...其他代码
}

2. 正确Present Sheet

在需要展示sheet的地方,配置并present,同时更新状态:

func showSheet() {
    let sheetVC = YourSheetContentViewController()
    sheetVC.modalPresentationStyle = .pageSheet
    
    // 配置sheet的样式(如高度、拖拽行为等)
    if let sheetPC = sheetVC.sheetPresentationController {
        sheetPC.detents = [.medium(), .large()]
        sheetPC.prefersGrabberVisible = true
    }
    
    present(sheetVC, animated: true) { [weak self] in
        self?.isSheetPresented = true
        self?.sheetVC = sheetVC
    }
    
    // 监听sheet自行dismiss的事件,更新状态
    sheetVC.presentationController?.delegate = self
}

3. 监听Sheet自行Dismiss

实现UIAdaptivePresentationControllerDelegate,处理sheet被用户手动关闭的情况:

extension YourCurrentViewController: UIAdaptivePresentationControllerDelegate {
    func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
        isSheetPresented = false
        sheetVC = nil
    }
}

4. 导航切换时控制Sheet可见性

利用ViewController的生命周期方法,在页面离开/返回导航栈顶部时处理sheet:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    // 仅在当前页面被push出导航栈时处理
    if isMovingFromParent, isSheetPresented {
        // 无动画关闭sheet,避免与导航动画冲突
        dismiss(animated: false) { [weak self] in
            self?.isSheetPresented = true // 保留状态,用于返回时恢复
        }
    }
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // 返回当前页面时,若之前sheet是显示状态则恢复
    if isSheetPresented {
        showSheet()
    }
}

最佳实践

  • 状态独立存储:如果sheet需要保留用户输入状态(如表单内容),将状态存在当前ViewController中,而非sheet内部,恢复展示时直接赋值即可。
  • 避免内存泄漏:始终用weak引用sheet的ViewController,同时监听dismiss事件及时清空引用。
  • 动画协调:导航切换时处理sheet用animated: false,避免和系统导航动画产生冲突,保证流畅性。
  • 代理解耦:如果当前页面是导航控制器的代理,也可以通过navigationController(_:didShow:animated:)方法监听页面切换,实现相同逻辑,但生命周期方法更直接贴合页面绑定的需求。

内容的提问来源于stack exchange,提问作者Betul Aksu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 12:10:16