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

如何检测UISplitViewController显示模式变化并控制关闭按钮显隐

解决UISplitViewController分屏模式下动态显示/隐藏关闭按钮的问题

这个问题我熟!你已经搞定了初始状态的显示逻辑,现在就差监听分屏模式的动态变化了,给你两种靠谱的方案,任选其一就行:

方案一:用NotificationCenter监听主控制器可见性变化

苹果专门提供了一个通知来监听UISplitViewController主控制器的可见性变化,非常贴合你的需求。

步骤:

  1. 在次级视图控制器的viewDidLoad中注册通知监听
  2. 实现通知处理方法,统一更新关闭按钮的显示状态
  3. 记得在控制器销毁时移除监听,避免内存泄漏
class YourSecondaryViewController: UIViewController {
    // 假设你已经定义了关闭按钮
    private let closeBarButtonItem = UIBarButtonItem(title: "关闭", style: .plain, target: self, action: #selector(closeTapped))

    override func viewDidLoad() {
        super.viewDidLoad()
        // 注册通知,只监听当前splitViewController的变化
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(updateCloseButtonVisibility),
            name: UISplitViewController.didChangeVisibilityOfPrimaryViewControllerNotification,
            object: splitViewController
        )
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // 初始化按钮状态
        updateCloseButtonVisibility()
    }

    @objc private func updateCloseButtonVisibility() {
        // 主控制器未隐藏(即并排模式)时显示关闭按钮,否则隐藏
        let shouldShow = !splitViewController!.primaryHidden
        navigationItem.leftBarButtonItem = shouldShow ? closeBarButtonItem : nil
    }

    @objc private func closeTapped() {
        // 处理关闭逻辑,比如切换到叠层模式或返回主控制器
        splitViewController?.preferredDisplayMode = .primaryOverlay
    }

    deinit {
        // 移除监听
        NotificationCenter.default.removeObserver(self)
    }
}

方案二:用UISplitViewControllerDelegate监听模式变化

如果你更倾向于用代理模式,也可以通过实现分屏控制器的代理方法来处理变化。

步骤:

  1. 在次级控制器中设置splitViewController的代理
  2. 实现代理方法,更新按钮状态
class YourSecondaryViewController: UIViewController, UISplitViewControllerDelegate {
    private let closeBarButtonItem = UIBarButtonItem(title: "关闭", style: .plain, target: self, action: #selector(closeTapped))

    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置代理
        splitViewController?.delegate = self
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        updateCloseButtonVisibility()
    }

    private func updateCloseButtonVisibility() {
        let shouldShow = !splitViewController!.primaryHidden
        navigationItem.leftBarButtonItem = shouldShow ? closeBarButtonItem : nil
    }

    // 监听主控制器可见性变化的代理方法
    func splitViewController(_ svc: UISplitViewController, didChangeVisibilityOfPrimaryViewController visible: Bool) {
        updateCloseButtonVisibility()
    }

    @objc private func closeTapped() {
        splitViewController?.preferredDisplayMode = .primaryOverlay
    }
}

注意事项:

  • 如果你选择代理方案,要确保没有其他对象(比如父控制器)同时设置了splitViewController的代理,否则会覆盖导致失效。
  • 两种方案都复用了updateCloseButtonVisibility方法,让代码更整洁,也方便后续修改逻辑。

内容的提问来源于stack exchange,提问作者Ted Hopp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:12:58