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

iOS13中Sheet关闭后如何刷新前一个ViewController?

解决iOS13中Sheet关闭后刷新前一个ViewController的问题

这个问题我之前也碰到过!iOS13之后,系统默认的模态呈现样式改成了UIModalPresentationStyle.pageSheet,这种情况下,被present的Sheet只是覆盖在原ViewController的视图上面,原VC的视图并没有被移除或隐藏,所以viewWillAppear、viewDidLoad这些生命周期方法自然不会被触发。下面给你几种实用的解决方案,按需选择即可:

方法1:闭包(Closure)—— 简单直接,适合轻量场景

闭包是最简单的实现方式,不需要额外定义协议,适合只需要通知原VC刷新、不需要传递复杂数据的场景。

步骤1:在设置ViewController中定义闭包属性

class SettingsViewController: UIViewController {
    // 定义一个可选闭包,用于通知原VC执行刷新操作
    var onDismiss: (() -> Void)?

    // 假设这是关闭按钮的点击事件
    @IBAction func closeButtonTapped(_ sender: UIButton) {
        dismiss(animated: true) {
            // 在Sheet完全关闭后调用闭包
            self.onDismiss?()
        }
    }
}

步骤2:在原ViewController中present时绑定闭包

class MainViewController: UIViewController {
    // 触发present设置页的方法
    @IBAction func showSettingsTapped(_ sender: UIButton) {
        guard let settingsVC = storyboard?.instantiateViewController(withIdentifier: "SettingsViewController") as? SettingsViewController else { return }
        
        // 绑定闭包,注意用[weak self]避免循环引用
        settingsVC.onDismiss = { [weak self] in
            self?.refreshCurrentView()
        }
        
        present(settingsVC, animated: true)
    }

    // 自定义的刷新视图方法
    private func refreshCurrentView() {
        // 这里写你的刷新逻辑,比如重新加载数据、更新UI控件
        tableView.reloadData()
        // ...其他操作
    }
}

方法2:代理(Delegate)—— 适合需要传递数据的复杂场景

如果你的设置页需要把用户修改的设置数据回传给原VC,代理模式会更清晰、更易于维护。

步骤1:定义代理协议

// 定义代理协议,注意用AnyObject确保只能被类遵守
protocol SettingsViewControllerDelegate: AnyObject {
    // 可以根据需求添加参数,比如传递修改后的设置数据
    func settingsViewControllerDidFinish(_ controller: SettingsViewController, updatedSettings: UserSettings?)
}

步骤2:在设置ViewController中添加代理属性

class SettingsViewController: UIViewController {
    // 弱引用代理,避免循环引用
    weak var delegate: SettingsViewControllerDelegate?
    // 假设这是用户修改后的设置数据
    private var updatedSettings: UserSettings?

    @IBAction func closeButtonTapped(_ sender: UIButton) {
        dismiss(animated: true) {
            // 通知代理刷新,并传递数据
            self.delegate?.settingsViewControllerDidFinish(self, updatedSettings: self.updatedSettings)
        }
    }
}

步骤3:原ViewController遵守并实现代理方法

class MainViewController: UIViewController, SettingsViewControllerDelegate {
    @IBAction func showSettingsTapped(_ sender: UIButton) {
        guard let settingsVC = storyboard?.instantiateViewController(withIdentifier: "SettingsViewController") as? SettingsViewController else { return }
        
        settingsVC.delegate = self
        present(settingsVC, animated: true)
    }

    // 实现代理方法
    func settingsViewControllerDidFinish(_ controller: SettingsViewController, updatedSettings: UserSettings?) {
        // 先处理回传的数据,再刷新视图
        if let settings = updatedSettings {
            // 保存设置数据
            UserDefaults.standard.set(settings.isDarkMode, forKey: "DarkMode")
        }
        // 执行刷新
        refreshCurrentView()
    }

    private func refreshCurrentView() {
        // 刷新逻辑
    }
}

方法3:监听Sheet的自动关闭(比如下拉关闭)

如果你的Sheet允许用户通过下拉手势直接关闭(pageSheet默认支持),上面两种方法可能不会触发(因为用户没点击关闭按钮),这时候可以用UIAdaptivePresentationControllerDelegate来监听Sheet的关闭事件。

实现步骤

class MainViewController: UIViewController, UIAdaptivePresentationControllerDelegate {
    @IBAction func showSettingsTapped(_ sender: UIButton) {
        guard let settingsVC = storyboard?.instantiateViewController(withIdentifier: "SettingsViewController") as? SettingsViewController else { return }
        
        // 设置presentationController的代理
        settingsVC.presentationController?.delegate = self
        present(settingsVC, animated: true)
    }

    // 当Sheet被任何方式关闭时都会调用这个方法
    func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
        refreshCurrentView()
    }

    private func refreshCurrentView() {
        // 刷新逻辑
    }
}

你可以把这个方法和闭包/代理结合使用,确保无论用户是点击按钮还是下拉关闭,都能触发刷新。

方法4:通知中心(NotificationCenter)—— 尽量少用,适合跨多层VC的场景

通知中心的耦合度比较高,不好维护,除非你的刷新逻辑需要跨多个不相关的VC,否则不推荐使用。

步骤1:原ViewController添加通知观察者

class MainViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 添加通知观察者
        NotificationCenter.default.addObserver(self, selector: #selector(refreshCurrentView), name: NSNotification.Name("SettingsDidDismiss"), object: nil)
    }

    deinit {
        // 一定要在销毁时移除观察者,避免内存泄漏
        NotificationCenter.default.removeObserver(self)
    }

    @objc private func refreshCurrentView() {
        // 刷新逻辑
    }
}

步骤2:设置ViewController关闭时发送通知

class SettingsViewController: UIViewController {
    @IBAction func closeButtonTapped(_ sender: UIButton) {
        dismiss(animated: true) {
            // 发送通知
            NotificationCenter.default.post(name: NSNotification.Name("SettingsDidDismiss"), object: nil)
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:41:00