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

Swift模态呈现的SearchViewController搜索编辑模式下无法释放问题

问题

我有一个以模态方式呈现的SearchViewController,其中包含UISearchController。当下滑关闭该视图控制器时,只有当搜索栏不在编辑模式下,它才会被释放;必须先点击取消按钮,它才能被释放。如何确保即使在编辑模式下,该视图控制器也能被释放?我确认所有闭包中都没有强引用self的情况。

呈现方ViewController代码

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        addButton()
    }

    func addButton() {
        let mediumConfiguration = UIImage.SymbolConfiguration(scale: .large)
        var checkButtonImage = UIImage(systemName: "plus", withConfiguration: mediumConfiguration)
        checkButtonImage = checkButtonImage?.withTintColor(.label)
        
        let button = UIButton(type: .contactAdd)
        button.addTarget(self, action: #selector(onAddViewControllerButtonClicked(sender:)), for: .touchUpInside)
        
        view.addSubview(button)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    }
    @objc func onAddViewControllerButtonClicked(sender: UIButton) {
        
        let viewController = SearchViewController()
        viewController.view.backgroundColor = .secondarySystemBackground
        
        let navigationController = UINavigationController()
        navigationController.viewControllers = [viewController]
        
        self.present(navigationController, animated: true)
    }
}

被呈现方ViewController代码

class SearchViewController: UIViewController, UISearchBarDelegate, UISearchResultsUpdating {

    override func viewDidLoad() {
        super.viewDidLoad()
        configureSearchController()
    }

    var searchController: UISearchController?
    func configureSearchController() {
        //search
        searchController = UISearchController(searchResultsController: nil)
        searchController?.searchResultsUpdater = self
        searchController?.searchBar.delegate = self
        searchController?.hidesNavigationBarDuringPresentation = false
        searchController?.searchBar.searchBarStyle = .minimal
        searchController?.searchBar.keyboardType = .webSearch
        self.navigationItem.searchController?.searchBar.backgroundColor = .clear
        self.navigationItem.searchController = searchController
        self.navigationItem.hidesSearchBarWhenScrolling = false
        self.definesPresentationContext = true
        self.navigationItem.searchController = searchController
    }
    func updateSearchResults(for searchController: UISearchController) {
        return
    }

    //check deallocation
    deinit { print("\(NSStringFromClass(type(of: self))): deallocated") }
}
解决方案

问题根源在于UISearchController处于编辑状态时,会持有相关视图的强引用,导致模态控制器无法被及时释放。可以通过以下方式解决:

1. 在控制器即将消失时主动结束搜索状态

在SearchViewController中重写viewWillDisappear方法,强制结束搜索栏的编辑状态,断开额外的引用持有:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    // 取消搜索栏第一响应者,收起键盘
    searchController?.searchBar.resignFirstResponder()
    // 主动退出搜索激活状态
    searchController?.isActive = false
}

2. 调整definesPresentationContext设置

当前代码中self.definesPresentationContext = true会让SearchViewController成为搜索控制器的呈现上下文,可能导致不必要的引用链。可以移除这行代码(默认值为false),让模态导航控制器管理呈现上下文。

优化后的完整SearchViewController代码

class SearchViewController: UIViewController, UISearchBarDelegate, UISearchResultsUpdating {

    override func viewDidLoad() {
        super.viewDidLoad()
        configureSearchController()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        searchController?.searchBar.resignFirstResponder()
        searchController?.isActive = false
    }

    var searchController: UISearchController?
    func configureSearchController() {
        searchController = UISearchController(searchResultsController: nil)
        searchController?.searchResultsUpdater = self
        searchController?.searchBar.delegate = self
        searchController?.hidesNavigationBarDuringPresentation = false
        searchController?.searchBar.searchBarStyle = .minimal
        searchController?.searchBar.keyboardType = .webSearch
        // 修正原代码的空引用问题,直接修改searchController的搜索栏属性
        searchController?.searchBar.backgroundColor = .clear
        self.navigationItem.searchController = searchController
        self.navigationItem.hidesSearchBarWhenScrolling = false
        // 移除definesPresentationContext设置,使用默认值false
    }

    func updateSearchResults(for searchController: UISearchController) {
        return
    }

    deinit { print("\(NSStringFromClass(type(of: self))): deallocated") }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 05:57:21