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

