title: How to prevent search bar from disappearing on scroll? iOS Swift
body: <p>I am creating a contact app.  I have a scroll bar at the top of my table view.</p>
  
  <p><a href="https://i.stack.imgur.com/rJQRU.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/rJQRU.png" alt="You see a search bar"></a></p>
  
  <p>When I scroll down the search bar disapears.</p>
  
  <p><a href="https://i.stack.imgur.com/Y6Yq7.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Y6Yq7.png" alt="Now you dont"></a></p>
  
  <p>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.</p>
  
  <p>Here is a picture of my storyboard:</p>
  
  <p><a href="https://i.stack.imgur.com/3hW3p.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/3hW3p.png" alt="enter image description here"></a></p>
  
  <p>Here is my view controller code for if the solution is not in storyboard:</p>
  
  <pre><code>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 &lt; $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) -&gt; Int {
          return 1
      }
  
      //delegeate that tells tabel view how many cells to have
      override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -&gt; 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) -&gt; 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) -&gt; Bool in
  
              //filters contacts array
  
              var categoryMatch = (scope == "Title")
              var stringMatch = contact.name?.rangeOfString(searchText)
  
              return categoryMatch &amp;&amp; (stringMatch != nil)
  
          })
      }
  
      func searchDisplayController(controller: UISearchController, shouldReloadTableForSearchString searchString: String!) -&gt; Bool {
  
          self.filterContentForSearchText(searchString, scope: "Title")
  
          return true
  
      }
  
  
      func searchDisplayController(controller: UISearchController, shouldReloadTableForSearchScope searchOption: Int) -&gt; 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
  
          }
      }
  
  }
  </code></pre>
  
  <p>EDIT 1:</p>
  
  <p>Here are the steps I have taken based off Ryosuke Hiramatsu's solution:</p>
  
  <ol>
  <li>Command X the table view.</li>
  <li>Add a view.</li>
  <li>Command V the table view into the new view.</li>
  <li>In the view controller, change UITableViewController to UITableView</li>
  <li>Add an outlet to the view controller named table view.</li>
  <li>Remove the overrides in the table view functions.</li>
  <li>Remove this line of code: tableView.tableHeaderView = searchController.searchBar</li>
  <li>Go back to storyboard and move the search bar out of the table view.  It'll appear behind the table view. </li>
  <li>Move the table view down and the search bar up.</li>
  <li>Add necessary constraints.</li>
  </ol>
  
  <p>My View now looks like this:</p>
  
  <p><a href="https://i.stack.imgur.com/xaGJB.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/xaGJB.png" alt="2 Search Bars"></a></p>
  
  <p>When I scroll down:</p>
  
  <p><a href="https://i.stack.imgur.com/6SjZV.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/6SjZV.png" alt="1 Search Bar"></a></p>
  
  <p>My Storyboard:</p>
  
  <p><a href="https://i.stack.imgur.com/IODr1.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/IODr1.png" alt="Storyboard edit 1"></a></p>
  
  <p>And finally My updated view controller code:</p>
  
  <pre><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 &lt; $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) -&gt; Int {
      return 1
  }
  
  //delegeate that tells tabel view how many cells to have
  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -&gt; 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) -&gt; 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) -&gt; Bool in
  
          //filters contacts array
  
          var categoryMatch = (scope == "Title")
          var stringMatch = contact.name?.rangeOfString(searchText)
  
          return categoryMatch &amp;&amp; (stringMatch != nil)
  
      })
  }
  
  func searchDisplayController(controller: UISearchController, shouldReloadTableForSearchString searchString: String!) -&gt; Bool {
  
      self.filterContentForSearchText(searchString, scope: "Title")
  
      return true
  
  }
  
  
  func searchDisplayController(controller: UISearchController, shouldReloadTableForSearchScope searchOption: Int) -&gt; 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
  
      }
  }
  </code></pre>
  
  <p>}</p>
  
  <p>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.</p>