Search code examples
swiftuikit

Place and display UISearchController over other content


I'm confused on how to place and display a UISearchBar and it's results over other content (in this case, a SceneView). I've attached a screenshot of my storyboard, which has a container view with the associated UISearchBar inside of it. It seems this is the wrong way to go about it, as the UITableView of results is stuck inside of that small container view. I'm unsure of how to start building this properly and am looking for some advice on designing this. I want the search results to appear below the UISearchBar as the user starts typing. enter image description here


Solution

  • I'm not sure that i get your point, hopefully it's so.

    I've written a small sample project for you to check, it has a searchBar which displays the searchResults - from an hard coded array of String values - in a tableView over a randomView with a red background. I'm not used to storyboards so i've done it programmatically (but it's the same logic if you want to use storyboards), this might be a way to achieve what you are looking for.

    Note that queries are not case sensitive, there are some hard coded values and in general the UX is just not good enough, i didn't bother to refine the project as it's just illustrative. For the same reason, just test it out on an iPhone real device/simulator as it is optimized so.

    Let me know if this is what you wanted or not, in the second case i'll try to fix it to your needs.

    You just need to copy-paste it and run:

    import UIKit
    
    final class ViewController: UIViewController {
    
    private let array: [String] = ["Alpha", "Beta", "Gamma", "AlphaBis", "BetaBis", "Alpha", "Beta", "Gamma", "AlphaBis", "BetaBis", "Alpha", "Beta", "Gamma", "AlphaBis", "BetaBis", "Alpha", "Beta", "Gamma", "AlphaBis", "BetaBis", "Alpha", "Beta", "Gamma", "AlphaBis", "BetaBis", "Alpha", "Beta", "Gamma", "AlphaBis", "BetaBis"]
    private var searchResults: [String] = []
    
    private let searchBar: UISearchBar = {
        let searchBar = UISearchBar()
        searchBar.placeholder = "Search for something..."
        return searchBar
    }()
    
    private let tableView: UITableView = {
        let table = UITableView()
        table.showsHorizontalScrollIndicator = false
        table.isHidden = true
        table.register(UITableViewCell.self,
                       forCellReuseIdentifier: "cell")
        return table
    }()
    
    private let randomView: UIView = {
        let view = UIView()
        view.backgroundColor = .red
        return view
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(randomView)
        view.addSubview(searchBar)
        view.addSubview(tableView)
    
        tableView.delegate = self
        tableView.dataSource = self
    
        searchBar.delegate = self
        searchBar.becomeFirstResponder()
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        searchBar.frame = CGRect(x: 20,
                                 y: 100,
                                 width: view.bounds.size.width-40,
                                 height: 60)
        tableView.frame = CGRect(x: 20,
                                 y: searchBar.bounds.size.height+100,
                                 width: view.bounds.size.width-40,
                                 height: view.bounds.size.height-searchBar.bounds.size.height-100)
        randomView.frame = CGRect(x: view.bounds.size.width*0.175,
                                  y: view.bounds.size.height/3,
                                  width: view.bounds.size.width/1.5,
                                  height: view.bounds.size.width/1.5)
    }
    
    }
    
    extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return searchResults.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell",
                                                 for: indexPath)
        cell.textLabel?.text = searchResults[indexPath.row]
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 60
    }
    }
    
    extension ViewController: UISearchBarDelegate {
    
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        
        guard let text = searchBar.text, !text.replacingOccurrences(of: " ", with: "").isEmpty else {
            searchResults.removeAll()
            updateUI()
            return
        }
        searchResults.removeAll()
    
        filterResults(with: searchText)
    }
    
    
    func filterResults(with query: String) {
    
        let results: [String] = array.filter { $0.hasPrefix(query) }
    
        self.searchResults = results
    
        updateUI()
    }
    
    func updateUI() {
        if searchResults.isEmpty {
            tableView.isHidden = true
        }
        else {
            tableView.isHidden = false
            tableView.reloadData()
        }
    }
    
    }