UISearchController 关闭时屏幕滞后

Screen lags when UISearchController dismissed

预期:

点击 UIButton 时,显示 viewcontroller 模态,其中包含搜索控制器和带结果的表格视图。

点击列表中的项目时,将搜索栏的文本更改为所点击的内容,然后关闭 viewcontroller 回到原来的状态,现在 UIButton 设置为该文本。

实际:

UIButton 调用 segue 到 searchViewController。 searchViewController 显示并正确配置 searchController 和 tableView。 点击单元格调用退出转场,展开到原始屏幕并正确更新 UIButton 和搜索栏中的文本...

但是,展开后出现异常的白屏,这让我抓狂。

已尝试缓解措施:

  1. 退出 searchController 然后调用 segue 以编程方式
  2. 在 didSelectRowAt
  3. 中调用 self.dismiss(animated: true completion:nil)
  4. 通过以下方式将解雇放在主线程上:DispatchQueue.main.async { }
  5. 调用 self.presentingViewController?.dismiss(动画:真)

Video Demo of flashing

代码:

SearchDetailsViewController - Viewcontroller 放松到

import UIKit

class SearchDetailsViewController: UIViewController {

  @IBOutlet weak var destinationButton: UIButton!
  override func viewDidLoad() {
    super.viewDidLoad()
  }

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

    if searchDestination != "" {
        destinationButton.setTitle(searchDestination, for: UIControlState.normal)
        destinationButton.setTitleColor(UIColor.black, for: UIControlState.normal)
    } else {
        destinationButton.setTitle("Search Nearby", for: UIControlState.normal)
    }
  }

  @IBAction func unwindToSearchDetailsViewController(segue: UIStoryboardSegue){
  }
}

SearchViewController - 问题 child。我目前将 tableview 单元格作为情节提要中的退出 segue。

    class SearchViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating, UISearchBarDelegate, UISearchControllerDelegate {


    @IBOutlet weak var searchResultsTableView: UITableView!

    var destinationsObj:[String:[String]] = [:]
    var destinations:[String] = []
    var defaultDestinations:[String] = ["Search Nearby"]
    var filteredDestinations:[String] = ["Search Nearby"]
    var shouldShowSearchResults = false

    var searchActive:Bool = false
    var searchController: UISearchController!

    override func viewDidLoad() {
        super.viewDidLoad()

        defaultDestinations = recentSearches
        configureTableView()
        configureSearchController()

    }

    override func viewDidAppear(_ animated: Bool) {
        // Show search bar keyboard
        searchController.isActive = true
        DispatchQueue.main.async {
            self.searchController.searchBar.becomeFirstResponder()
        }

    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: Configure Functions
    func configureSearchController() {
        searchController = UISearchController(searchResultsController: nil) //nil lets the view controller also be the search results
        searchController.searchResultsUpdater = self
        searchController.dimsBackgroundDuringPresentation = false

        searchController.searchBar.placeholder = "Where to?"
        searchController.searchBar.delegate = self

        searchController.searchBar.sizeToFit()
        searchResultsTableView.tableHeaderView = searchController.searchBar
        searchController.delegate = self

    }

    func configureTableView() {
        searchResultsTableView.delegate = self
        searchResultsTableView.dataSource = self

        //searchResultsTableView.isMultipleTouchEnabled = false
    }

    // MARK: TableView Delegate Functions
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        if shouldShowSearchResults {
            return filteredDestinations.count
        } else {
            return defaultDestinations.count
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "idCell", for: indexPath)

        if shouldShowSearchResults {
            cell.textLabel?.text = filteredDestinations[indexPath.row]
        } else {

            cell.textLabel?.text = defaultDestinations[indexPath.row]
        }

        return cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 40.0
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {


        if let value = tableView.cellForRow(at: indexPath)?.textLabel?.text {
            self.searchController.searchBar.text = value
            searchDestination = value
            if !recentSearches.contains(value) {
                recentSearches.append(value)
            }

        }
        //self.searchController.resignFirstResponder()
//        tableView.deselectRow(at: indexPath, animated: false)
//        DispatchQueue.main.async {
//            self.dismiss(animated: true, completion: nil)
//        }

       // self.performSegue(withIdentifier: "cancelSearchSegue", sender: self)
    }

    // MARK: UISearchBar Delegate Functions
    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.resignFirstResponder()
        //self.dismiss(animated: true, completion: nil)
        self.performSegue(withIdentifier: "cancelSearchSegue", sender: self)
    }

    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {

        if let value = searchBar.text {
            searchDestination = value
            if !recentSearches.contains(value) {
                recentSearches.append(value)
            }
        }


        //self.dismiss(animated: true, completion: nil)
        self.performSegue(withIdentifier: "cancelSearchSegue", sender: self)
    }

    func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {

    }


    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        shouldShowSearchResults = true
        if searchText.characters.count > 1 {
            return
        } else {
            if let firstLetter = searchText.characters.first{
                print("Typed \(firstLetter)")
                getPredictionData(firstLetter:firstLetter.description)
            }
        }
    }

    func dismissCurrentView() {
       // self.presentingViewController?.dismiss(animated: true, completion: nil)
        self.performSegue(withIdentifier: "cancelSearchSegue", sender: self)
    }

Screenshot of my storyboard

好吧,我想我 post 答案是为了防止其他人遇到这种情况。

在 ViewDidAppear 中,我将 searchController 设置为活动 searchController.isActive = 真

在我解散之前,我需要将其设置为不活动!

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  if let value = tableView.cellForRow(at: indexPath)?.textLabel?.text {
    self.searchController.searchBar.text = value
    searchDestination = value
    if !recentSearches.contains(value) {
        recentSearches.append(value)
    }
  }
 self.searchController.isActive = false
 self.performSegue(withIdentifier: "cancelSearchSegue", sender: self)
}

不要执行 segue,尝试直接关闭视图控制器并在关闭之前将呈现视图控制器的 属性 设置为搜索结果