首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法显示UISearchController

无法显示UISearchController
EN

Stack Overflow用户
提问于 2018-05-21 15:05:53
回答 2查看 1.9K关注 0票数 2

我有以下视图层次结构:

代码语言:javascript
复制
                         UINavigationController
                                  ||
                                  \/
           LibraryTableViewController: UITableViewController
                                  ||
                                  \/
       AlbumsCollectionViewController: UICollectionViewController
                                  ||
                                  \/
             SongsTableViewController: UITableViewController

我希望在AlbumsCollectionViewController中有一个搜索栏,在SongsTableViewController中有一个不同的搜索栏,这个搜索栏显示在navigationItem.titleView中。

我设法在AlbumsCollectionViewController中添加了一个工作搜索栏,如下所示:

代码语言:javascript
复制
class AlbumsCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UISearchControllerDelegate, UISearchResultsUpdating, UISearchBarDelegate {

    var searchController : UISearchController!

    override func viewDidLoad() {
        super.viewDidLoad()

        initSearchBar()
        initNavigationBar()
    }

    private func initSearchBar() {
        self.searchController = UISearchController(searchResultsController:  nil)

        self.searchController.searchResultsUpdater = self
        self.searchController.delegate = self
        self.searchController.searchBar.delegate = self

        self.searchController.hidesNavigationBarDuringPresentation = false
        self.searchController.dimsBackgroundDuringPresentation = false

        searchController.searchResultsController?.view.isHidden = false
        searchController.hidesNavigationBarDuringPresentation = false

        self.extendedLayoutIncludesOpaqueBars = true
        self.definesPresentationContext = true

        searchController.searchBar.backgroundColor = UIColor.black
        UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes([NSAttributedStringKey.foregroundColor : UIColor.white], for: .normal)

        self.navigationItem.titleView = searchController.searchBar

        navigationItem.titleView?.isHidden = true
    }

    private func initNavigationBar() {
        searchButton.tintColor = UIColor.white
        settingsButton.tintColor = UIColor.white
        backButton.tintColor = UIColor.white
        self.navigationItem.title = "Artists"
        self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor : UIColor.white]
    }


    @IBAction func SearchButtonTapped(_ sender: Any) {
        showSearchBar()
    }


    private func showSearchBar(){
        navigationItem.titleView?.isHidden = false
        searchController.isActive = true
    }
}

请注意,搜索栏隐藏在ViewDidLoad()上,并在按下按钮时出现,如SearchButtonTapped方法中所示。

现在,我试图在SongsTableViewController中做同样的事情,但是,当点击按钮(即调用SearchButtonTapped)时,搜索栏没有显示,我得到了以下消息:

代码语言:javascript
复制
Warning: Attempt to present <UISearchController: 0x7f8158812b50> on <MyProject.AlbumsCollectionViewController: 0x7f81588023c0> whose view is not in the window hierarchy!

如果我评论了行searchController.isActive = true,那么搜索栏将显示,但是,即使我点击它,它也不会是活动的。

编辑

抱歉我没说清楚。我在SongsTableViewController中有一个单独的SongsTableViewController。我的意思是在两个控制器中使用相同的逻辑。

还请注意,如果我从导航控制器(即视图层次结构只有2个控制器( SongsTableViewController => SongsTableViewController) )中推送,则搜索栏工作良好()

这是SongsTableViewController (省略的非相关内容)的大部分代码

代码语言:javascript
复制
import UIKit
import os.log
import MediaPlayer

class SongsTableViewController: UITableViewController, UISearchControllerDelegate, UISearchResultsUpdating, UISearchBarDelegate ,PlayerDelegate, NowPlayingDelegate, SongCellDelegate, SongsOptionsDelegate {

    // MARK: properties

    var playerManager: PlayerManager? = nil
    var dataManager: DataManager? = nil

    var tabVC: TabBarController?
    var selectedSong: Song?

    lazy var optionsTransitionDelegate = PresentationManager()
    lazy var playlistTransitionDelegate = PresentationManager()

    var searchController : UISearchController!

    @IBOutlet var backgroundView: UIView!
    @IBOutlet weak var searchButton: UIBarButtonItem!
    @IBOutlet weak var settingsButton: UIBarButtonItem!

    var albumID: String?
    var artistID: String?
    var playlist: Playlist?

    var songs = [Song]()
    var songIndexMap = [String: Int]()
    var filteredSongs = [Song]()


    override func viewDidLoad() {
        super.viewDidLoad()
        self.dataManager = DataManager.getInstance()
        self.playerManager = PlayerManager.getInstance()

        playlistTransitionDelegate.screenRatio = 2.0 / 3.0

        if(self.albumID != nil) {
            self.songs = SQLiteManager.getAlbumSongs(albumID: self.albumID!)
        } else if(self.artistID != nil) {
            self.songs = SQLiteManager.getArtistSongs(artistID: self.artistID!)
        } else if (self.playlist != nil) {
            self.songs = SQLiteManager.getPlaylistSongs(playlist: self.playlist!)
        } else {
            dataManager?.songsTableViewController = self
        }

        for i in 0..<songs.count {
            songIndexMap[songs[i].id] = i
        }

        initSearchBar()
        initNavigationBar()

        if(songs.count == 0 && (!fullListOfSongs() || fullListOfSongs() && dataManager?.getFullSongsCount() == 0)){
            tableView.backgroundView = backgroundView
        }
        tableView.tableFooterView = UIView()

        tabVC = tabBarController as? TabBarController
        tabVC?.nowPlayingViewController?.delegate = self


    }



    private func shouldAutorotate() -> Bool {
        return false
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return Util.SONG_CELL_HEIGHT
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if(isFiltering()) {
            return self.filteredSongs.count
        } else if (fullListOfSongs()) {
            return dataManager!.getFullSongsCount()
        }
        return self.songs.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellIdentifier = "SongTableViewCell"
        guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? SongCell  else {
            fatalError("The dequeued cell is not an instance of SongCell.")
        }
        var song: Song?
        if(fullListOfSongs()) {
            if(isFiltering()){
                song = self.filteredSongs[indexPath.row]
            } else {
                song = dataManager?.getSong(index: indexPath.row)
            }
        } else {
            if(isFiltering()){
                song = self.filteredSongs[indexPath.row]
            } else {
                song = self.songs[indexPath.row]
            }
        }

        cell.setAttributes(song: song!)
        cell.delegate = self

        cell.preservesSuperviewLayoutMargins = false
        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
        self.tableView.deselectRow(at: indexPath, animated: false)
    }



    // MARK: - Search Bar

    func updateSearchResults(for searchController: UISearchController) {
        if (!searchController.isActive) {
            hideSearchBar()
            tableView.reloadData()
        }

        if(isSearchBarEmpty()) {
            return
        }

        filterSongs(filter: searchController.searchBar.text!)
        tableView.reloadData()
    }

    private func filterSongs(filter: String) {
        if(self.albumID != nil) {
            self.filteredSongs = SQLiteManager.getAlbumSongs(albumID: self.albumID!, filter: filter)
        } else if(self.artistID != nil) {
            self.filteredSongs = SQLiteManager.getArtistSongs(artistID: self.artistID!, filter: filter)
        } else if(self.playlist != nil) {
            self.filteredSongs = SQLiteManager.getPlaylistSongs(playlist: self.playlist!, filter: filter)
        }else {
            self.filteredSongs = SQLiteManager.getSongs(filter: filter)
        }
    }

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        if searchText == "" {
            tableView.reloadData()
        }
    }


    private func initSearchBar() {
        self.searchController = UISearchController(searchResultsController:  nil)

        self.searchController.searchResultsUpdater = self
        self.searchController.delegate = self
        self.searchController.searchBar.delegate = self

        self.searchController.hidesNavigationBarDuringPresentation = false
        self.searchController.dimsBackgroundDuringPresentation = false

        searchController.searchResultsController?.view.isHidden = false
        searchController.hidesNavigationBarDuringPresentation = false

        self.extendedLayoutIncludesOpaqueBars = true
        self.definesPresentationContext = true

        searchController.searchBar.backgroundColor = UIColor.black
        UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes([NSAttributedStringKey.foregroundColor : UIColor.white], for: .normal)

        self.navigationItem.titleView = searchController.searchBar

        navigationItem.titleView?.isHidden = true
    }


    private func initNavigationBar() {
        searchButton.tintColor = UIColor.white
        if (fullListOfSongs()) {
            searchButton.isEnabled = false
            dataManager?.buttons.append(searchButton)
        }
        settingsButton.tintColor = UIColor.white
        self.navigationItem.title = "Songs"
        self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor : UIColor.white]
    }


    @IBAction func SearchButtonTapped(_ sender: Any) {
        showSearchBar()
    }


    private func showSearchBar(){
        self.navigationItem.titleView?.isHidden = false
        self.searchController.isActive = true

        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
            self.searchController.searchBar.becomeFirstResponder()
        }

        navigationItem.rightBarButtonItems![0].isEnabled = false
        navigationItem.rightBarButtonItems![0].image = nil
        navigationItem.rightBarButtonItems![1].isEnabled = false
        navigationItem.rightBarButtonItems![1].image = nil
    }

    private func hideSearchBar() {
        navigationItem.titleView?.isHidden = true

        navigationItem.rightBarButtonItems![0].isEnabled = true
        navigationItem.rightBarButtonItems![0].image = UIImage(named: "settings")
        navigationItem.rightBarButtonItems![1].isEnabled = true
        navigationItem.rightBarButtonItems![1].image = UIImage(named: "search")

    }

    func isFiltering() -> Bool {
        if(searchController == nil){
            return false
        }
        return searchController.isActive && !isSearchBarEmpty()
    }

    private func isSearchBarEmpty() -> Bool {
        return searchController.searchBar.text?.isEmpty ?? true
    }

    private func fullListOfSongs() -> Bool {
        return self.playlist == nil && self.albumID == nil && self.artistID == nil
    }

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-24 18:35:10

这在我测试的时候奏效了。我相信问题在SongsTableViewControllerself.definesPresentationContext = false中。这应该是推视图控制器的true。(见docs 这里)

对于SongsTableViewController (推送视图控制器),添加以下内容:

代码语言:javascript
复制
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.definesPresentationContext = true
}

并将其添加到AlbumsCollectionViewController (初始视图控制器):

代码语言:javascript
复制
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    self.definesPresentationContext = false
}
票数 2
EN

Stack Overflow用户

发布于 2018-05-22 05:12:46

当您在SongsTableViewController上时,AlbumsCollectionViewController不在窗口层次结构中。

我能理解的是,您正在从showSearchBar调用AlbumsCollectionViewControllerSongsTableViewController方法。由于您从AlbumsCollectionViewController导航到SongsTableViewController,所以您的AlbumsCollectionViewController不在窗口层次结构中,因此无法显示搜索控制器。

要修复,请尝试在SongsTableViewController中添加一个单独的搜索栏控制器,就像您以前在AlbumsCollectionViewController中所做的那样。

或者,您可以创建一个独立的视图控制器,实现搜索功能,然后将其从两个控制器中呈现出来。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50451647

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档