How to prevent search bar from disappearing on scr

2019-01-25 23:00发布

I am creating a contact app. I have a scroll bar at the top of my table view.

You see a search bar

When I scroll down the search bar disapears.

Now you dont

How to prevent search bar from disappearing on scroll? I want it to stay at the top of the page at all times like in the first picture.

Here is a picture of my storyboard:

enter image description here

Here is my view controller code for if the solution is not in storyboard:

class ViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate, UISearchResultsUpdating {

    //manages search bar
    var searchController:UISearchController!

    var contacts = [Contact]()

    //array to hold contacts that match the search results
    var filteredContacts = [Contact]()

    override func viewDidLoad() {

        super.viewDidLoad()

        //initialize the defaults manager class
        NSUserDefaultsManager.initializeDefaults()

        //search controller
        searchController = UISearchController(searchResultsController: nil)
        searchController.searchBar.sizeToFit()
        tableView.tableHeaderView = searchController.searchBar
        definesPresentationContext = true

        searchController.searchResultsUpdater = self
        searchController.dimsBackgroundDuringPresentation = false

        //load the contacts
        title = "Contacts"

        tableView.backgroundView = UIImageView(image: UIImage(named: "valblur15"))

        contacts = [Contact]()
        let api = ContactAPI()
        api.loadContacts(didLoadContacts)

    }

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

        //reload the table view to check for new contacts
        tableView.reloadData()

        //set the color of the nav bar to valbruna yellow
        navigationController?.navigationBar.backgroundColor = UIColor(red: 254.0/255.0, green: 196.0/255.0, blue: 37.0/255.0, alpha: 0.95)

    }

    //MARK: -Helper Methods

    // Uupdate searching results
    func updateSearchResultsForSearchController(searchController: UISearchController) {

        let searchText = searchController.searchBar.text
        filterContentForSearchText(searchText)
        tableView.reloadData()

    }

    func filterList() { // should probably be called sort and not filter

        //sort contacts from a-z
        contacts.sort() { $0.name < $1.name }

        //remove contacts whose locations are nil
        contacts = contacts.filter() { $0.location != "nil"}

        //remove contacts whose titles phone email and department are all nil
        contacts = contacts.filter() {
            if($0.title != "" || $0.phone != "" || $0.email != "" || $0.department != ""){
                return true
            }
            return false
        }


        tableView.reloadData()
    }

    func didLoadContacts(contacts: [Contact]){
        self.contacts = contacts
        filterList()
        tableView.reloadData()
    }

    //MARK: -Table View

    //set number opf sections in table view
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    //delegeate that tells tabel view how many cells to have
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //return size of array

        //if searching show count of filtered contacts
        if (searchController.active){

            return self.filteredContacts.count

        }else{

            return self.contacts.count

        }

    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = self.tableView.dequeueReusableCellWithIdentifier("customcell") as! CustomCell //from the customcell class

        //change color of cell text label
        cell.textLabel?.textColor = UIColor.blackColor()
        cell.backgroundColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 0.8)

        let contact : Contact

        //if users is searching then return filtered contacts
        if (searchController.active){

            contact = self.filteredContacts[indexPath.row]

        }else{

            contact = self.contacts[indexPath.row]

        }


        //handel assignment of text
        cell.textLabel?.text = contact.name

        //retrieve from customcell class
        cell.contact = contact

        return cell
    }


    //MARK: -Search

    func filterContentForSearchText(searchText: String, scope: String = "Title")
    {
        self.filteredContacts = self.contacts.filter({( contact: Contact) -> Bool in

            //filters contacts array

            var categoryMatch = (scope == "Title")
            var stringMatch = contact.name?.rangeOfString(searchText)

            return categoryMatch && (stringMatch != nil)

        })
    }

    func searchDisplayController(controller: UISearchController, shouldReloadTableForSearchString searchString: String!) -> Bool {

        self.filterContentForSearchText(searchString, scope: "Title")

        return true

    }


    func searchDisplayController(controller: UISearchController, shouldReloadTableForSearchScope searchOption: Int) -> Bool {

        self.filterContentForSearchText(self.searchController!.searchBar.text, scope: "Title")

        return true

    }

    //MARK: -Segue

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if(segue.identifier == "detailview"){
            let cell = sender as! CustomCell
            let detailView = segue.destinationViewController as! DetailViewController
            detailView.preContact = cell.contact

        }
    }

}

EDIT 1:

Here are the steps I have taken based off Ryosuke Hiramatsu's solution:

  1. Command X the table view.
  2. Add a view.
  3. Command V the table view into the new view.
  4. In the view controller, change UITableViewController to UITableView
  5. Add an outlet to the view controller named table view.
  6. Remove the overrides in the table view functions.
  7. Remove this line of code: tableView.tableHeaderView = searchController.searchBar
  8. Go back to storyboard and move the search bar out of the table view. It'll appear behind the table view.
  9. Move the table view down and the search bar up.
  10. Add necessary constraints.

My View now looks like this:

2 Search Bars

When I scroll down:

1 Search Bar

My Storyboard:

Storyboard edit 1

And finally My updated view controller code:

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchResultsUpdating {


@IBOutlet var tableView: UITableView!


//manages search bar
var searchController:UISearchController!

var contacts = [Contact]()

//array to hold contacts that match the search results
var filteredContacts = [Contact]()

override func viewDidLoad() {

    super.viewDidLoad()

    //initialize the defaults manager class
    NSUserDefaultsManager.initializeDefaults()

    //search controller
    searchController = UISearchController(searchResultsController: nil)
    searchController.searchBar.sizeToFit()
    definesPresentationContext = true

    tableView.tableHeaderView = searchController.searchBar

    searchController.searchResultsUpdater = self
    searchController.dimsBackgroundDuringPresentation = false

    //load the contacts
    title = "Valbruna Contacts"

    tableView.backgroundView = UIImageView(image: UIImage(named: "valblur15"))

    contacts = [Contact]()
    let api = ContactAPI()
    api.loadContacts(didLoadContacts)

}

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

    //reload the table view to check for new contacts
    tableView.reloadData()

    //set the color of the nav bar to valbruna yellow
    navigationController?.navigationBar.backgroundColor = UIColor(red: 254.0/255.0, green: 196.0/255.0, blue: 37.0/255.0, alpha: 0.95)

}

//MARK: -Helper Methods

// Uupdate searching results
func updateSearchResultsForSearchController(searchController: UISearchController) {

    let searchText = searchController.searchBar.text
    filterContentForSearchText(searchText)
    tableView.reloadData()

}

func filterList() { // should probably be called sort and not filter

    //sort contacts from a-z
    contacts.sort() { $0.name < $1.name }

    //remove contacts whose locations are nil
    contacts = contacts.filter() { $0.location != "nil"}

    //remove contacts whose titles phone email and department are all nil
    contacts = contacts.filter() {
        if($0.title != "" || $0.phone != "" || $0.email != "" || $0.department != ""){
            return true
        }
        return false
    }


    tableView.reloadData()
}

func didLoadContacts(contacts: [Contact]){
    self.contacts = contacts
    filterList()
    tableView.reloadData()
}

//MARK: -Table View

//set number opf sections in table view
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

//delegeate that tells tabel view how many cells to have
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    //return size of array

    //if searching show count of filtered contacts
    if (searchController.active){

        return self.filteredContacts.count

    }else{

        return self.contacts.count

    }

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = self.tableView.dequeueReusableCellWithIdentifier("customcell") as! CustomCell //from the customcell class

    //change color of cell text label
    cell.textLabel?.textColor = UIColor.blackColor()
    cell.backgroundColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 0.8)

    let contact : Contact

    //if users is searching then return filtered contacts
    if (searchController.active){

        contact = self.filteredContacts[indexPath.row]

    }else{

        contact = self.contacts[indexPath.row]

    }


    //handel assignment of text
    cell.textLabel?.text = contact.name

    //retrieve from customcell class
    cell.contact = contact

    return cell
}


//MARK: -Search

func filterContentForSearchText(searchText: String, scope: String = "Title")
{
    self.filteredContacts = self.contacts.filter({( contact: Contact) -> Bool in

        //filters contacts array

        var categoryMatch = (scope == "Title")
        var stringMatch = contact.name?.rangeOfString(searchText)

        return categoryMatch && (stringMatch != nil)

    })
}

func searchDisplayController(controller: UISearchController, shouldReloadTableForSearchString searchString: String!) -> Bool {

    self.filterContentForSearchText(searchString, scope: "Title")

    return true

}


func searchDisplayController(controller: UISearchController, shouldReloadTableForSearchScope searchOption: Int) -> Bool {

    self.filterContentForSearchText(self.searchController!.searchBar.text, scope: "Title")

    return true

}

//MARK: -Segue

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if(segue.identifier == "detailview"){
        let cell = sender as! CustomCell
        let detailView = segue.destinationViewController as! DetailViewController
        detailView.preContact = cell.contact

    }
}

}

My Problem now is that only the first search bar is stationary and it doesn't search when I type in it. The second search bar disappears on scroll. Also when I click a name it no longer segues to the next view.

4条回答
老娘就宠你
2楼-- · 2019-01-25 23:12

You are adding a UISearchController as your UITableView's headerView. Table view headers are not "sticky", and scroll with the cells as the user scrolls through the table. Consider creating a section header and adding your UISearchController there in viewForHeaderInSection.

查看更多
对你真心纯属浪费
3楼-- · 2019-01-25 23:20

Problem is view hierarchy.

Your storyboard is this:

enter image description here

Search Bar is added on TableView.

Correct hierarchy is this:

enter image description here

You change UITableViewController to UIViewController, and appending SearchDisplayController while being careful about view hierarcy.

It will work :)

查看更多
Luminary・发光体
4楼-- · 2019-01-25 23:27

I think the problem arise because you have added search bar as table header view.

tableView.tableHeaderView = searchController.searchBar

try to add search bar in self.view like this:

self.view. addsubview("Yore search bar")

hope this will solve your problem

查看更多
啃猪蹄的小仙女
5楼-- · 2019-01-25 23:29

iOS9

Got the same problem. I added the searchbar programmatically. Here's how i have fixed mine. Might help in the future :)

I have added the searchController.searchBar on tableview's viewForHeaderInSectioninstead on adding to tableView.tableHeaderView.

Remove this line if present. tableView.tableHeaderView = searchController.searchBar

Then implement this on tableview's delegates.

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    return self.searchController.searchBar
}

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return searchController.searchBar.frame.height
}

Hope it helps !

查看更多
登录 后发表回答