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

重写UIViewController的show(_:sender:)方法致UI冻结,求解决办法

问题:重写UIViewController的show(_:sender:)导致UI冻结(iOS 17.4/Xcode 15.3)

在Xcode 15.3模拟器、iOS 17.4、macOS Sonoma 14.3.1、MacBook Air M1 8GB环境下,重写UIViewController的show(_:sender:)方法后,调用该方法时应用会出现UI冻结。调用重写后的present(_:animated:completion)方法无异常,点击右侧导航栏按钮触发show(_:sender:)时会触发冻结。

复现代码

class ViewController: UIViewController {
    let tableView = UITableView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
                
        navigationItem.leftBarButtonItem = .init(title: "Present", style: .plain, target: self, action: #selector(presentViewController))
        navigationItem.rightBarButtonItem = .init(title: "Show", style: .done, target: self, action: #selector(showViewController))
        
        view.addSubview(tableView)
        tableView.frame = view.bounds
        tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        tableView.dataSource = self
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    }
    
    @objc func presentViewController() {
        present(AnotherViewController(), animated: true)
    }

    override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
        super.present(viewControllerToPresent, animated: flag, completion: completion)
    }
    
    @objc func showViewController() {
        show(AnotherViewController(), sender: self)
    }
    
    override func show(_ vc: UIViewController, sender: Any?) {
        super.show(vc, sender: sender)
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        1
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        var contentConfiguration = cell.defaultContentConfiguration()
        contentConfiguration.text = "Cell"
        cell.contentConfiguration = contentConfiguration
        return cell
    }
}

class AnotherViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBlue
    }
}

可行解决方法

  • 移除空重写方法:如果重写show(_:sender:)没有额外逻辑,直接删除该重写方法即可恢复正常。空实现可能触发了iOS 17.4模拟器的内部状态异常。
  • 手动实现导航栈逻辑:若必须重写该方法,可显式处理导航控制器的push操作,绕过系统异常路径:
    override func show(_ vc: UIViewController, sender: Any?) {
        if let navController = navigationController {
            navController.pushViewController(vc, animated: true)
        } else {
            super.show(vc, sender: sender)
        }
    }
    
  • 升级开发环境版本:该问题属于Xcode 15.3与iOS 17.4模拟器的已知bug,升级到Xcode 15.4+、iOS 17.5+及以上版本通常能修复此问题。
  • 替换为直接push调用:在触发跳转时,直接使用pushViewController替代show(_:sender:),避免触发重写带来的异常:
    @objc func showViewController() {
        navigationController?.pushViewController(AnotherViewController(), animated: true)
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 01:05:20