【问题标题】:Swift search bar(controller) memory leaksSwift 搜索栏(控制器)内存泄漏
【发布时间】:2019-10-13 01:35:12
【问题描述】:

我有一个主屏幕,有一个按钮,我可以在该按钮上切换到 searchVC 屏幕。我在它们之间有一个导航控制器,在 searchVC 中有 searchControllersearchBar

问题:我需要在屏幕出现时激活搜索,但是 searchBar 激活(点击或becomeFirstResponder()导致内存泄漏下图)

我尝试删除代表,问题消失了,但我需要知道何时按下取消按钮以继续/关闭到 mainVC

代码:tableView 用于结果,resultView 带有标签用于空结果

class SearchViewController: UIViewController,UISearchBarDelegate,UISearchControllerDelegate {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var resultView: ResultView!

let searchController = UISearchController(searchResultsController: nil)

var filteredSongs = [SongListModel]()
var songs = SongListModel.fetchSongs()


override func viewDidLoad() {
    super.viewDidLoad()

    searchController.searchResultsUpdater = self
    searchController.obscuresBackgroundDuringPresentation = false
    searchController.searchBar.placeholder = "Search songs"
    if #available(iOS 11.0, *) {
        navigationItem.titleView = searchController.searchBar
        navigationItem.hidesSearchBarWhenScrolling = false
        //            navigationController?.navigationBar.topItem?.searchController = searchController
        //            navigationItem.titleView?.isHidden = true
        searchController.dimsBackgroundDuringPresentation = false
        searchController.hidesNavigationBarDuringPresentation = false
    } else {
        tableView.tableHeaderView = searchController.searchBar
    }
    searchController.searchBar.showsCancelButton = true
    searchController.definesPresentationContext = true

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

    tableView.keyboardDismissMode = .interactive
}


override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    delay(0.1) { [unowned self] in
        self.searchController.searchBar.becomeFirstResponder()
    }


}
func delay(_ delay: Double, closure: @escaping ()->()) {
    let when = DispatchTime.now() + delay
    DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}


func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    searchController.searchBar.resignFirstResponder()
}

func searchBarIsEmpty() -> Bool {
    // Returns true if the text is empty or nil
    return searchController.searchBar.text?.isEmpty ?? true
}

func filterContentForSearchText(_ searchText: String, scope: String = "All") {
    filteredSongs = songs.filter({( song : SongListModel) -> Bool in
        return song.musicFileName.lowercased().contains(searchText.lowercased())
    })

    tableView.reloadData()
}

func isFiltering() -> Bool {
    return searchController.isActive && !searchBarIsEmpty()
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    searchController.searchBar.endEditing(true)
    searchController.searchBar.resignFirstResponder()
    //        searchController.searchBar.delegate = nil
    //        searchController.searchResultsUpdater = nil


    dismiss(animated: true, completion: nil)
}


// MARK: - Navigation

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "PlayTilesSegue", let destinationVC = segue.destination as? TilesViewController, let selectedIndex = tableView.indexPathForSelectedRow?.row {
        let song: SongListModel
        if isFiltering() {
            song = filteredSongs[selectedIndex]
        } else {
            song = songs[selectedIndex]
        }
        destinationVC.songFileName = song.musicFileName
        navigationController?.setNavigationBarHidden(true, animated: false)
    }
}
}
extension SearchViewController: UITableViewDelegate,UITableViewDataSource {


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if isFiltering() {
        resultView.setIsFilteringToShow(filteredItemCount: filteredSongs.count, of: songs.count)
        return filteredSongs.count
    }

    resultView.setNotFiltering()
    return songs.count

}

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

    let song: SongListModel

    if isFiltering() {
        song = filteredSongs[indexPath.row]
    } else {
        song = songs[indexPath.row]
    }

    cell.listenSongButton.setBackgroundImage(UIImage(named: "playback"), for: .normal)
    cell.filteredAuthorNameLabel.text = song.authorName
    cell.filteredSongNameLabel.text = song.songName
    cell.playGameButton.setTitle(song.playButton.rawValue, for: .normal)

    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    performSegue(withIdentifier: "PlayTilesSegue", sender: indexPath)
    tableView.deselectRow(at: indexPath, animated: true)

}



}

extension SearchViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        filterContentForSearchText(searchController.searchBar.text!)
    }
}

Image memory leaks

【问题讨论】:

    标签: ios swift memory-leaks uisearchbar uisearchcontroller


    【解决方案1】:

    在从父级移除 VC 时停用搜索控制器有助于避免内存泄漏:

    override func didMove(toParent parent: UIViewController?) {
        super.didMove(toParent: parent)
    
        if parent == nil, searchController.isActive {
            searchController.isActive = false
        }
    }
    

    【讨论】:

      【解决方案2】:

      您需要设置UISearchController searchBar 的委托。完成此操作后,将正确调用添加的委托方法 searchBarCancelButtonClicked:

      这里是it

      【讨论】:

      • 我知道,但问题是内存泄漏
      • 无论如何,如果你想消除内存泄漏,你可以在视图控制器的 deinit 函数中删除
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-29
      • 2020-03-19
      • 2013-01-27
      • 1970-01-01
      • 2012-07-30
      • 2012-11-16
      • 1970-01-01
      相关资源
      最近更新 更多