重写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
相关产品推荐
相关产品推荐

