如何防止搜索栏在滚动上消失? iOS Swift

时间:2015-07-29 13:49:44

标签: ios swift uitableview uisearchbar

我正在创建一个联系人应用。我在表格视图的顶部有一个滚动条。

You see a search bar

当我向下滚动搜索栏消失时。

Now you dont

如何防止搜索栏在滚动条上消失?我希望它始终保持在页面顶部,就像第一张图片一样。

这是我的故事板的图片:

enter image description here

如果解决方案不在故事板中,那么这是我的视图控制器代码:

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

        }
    }

}

编辑1:

以下是我根据Ryosuke Hiramatsu的解决方案采取的步骤:

  1. 命令X表视图。
  2. 添加视图。
  3. 将表视图命令为新视图。
  4. 在视图控制器中,将UITableViewController更改为UITableView
  5. 将插座添加到名为table view的视图控制器中。
  6. 删除表格视图函数中的替代。
  7. 删除以下代码行:tableView.tableHeaderView = searchController.searchBar
  8. 返回故事板并将搜索栏移出表格视图。它会出现在表格视图的后面。
  9. 向下移动表格视图并向上移动搜索栏。
  10. 添加必要的约束。
  11. 我的视图现在看起来像这样:

    2 Search Bars

    当我向下滚动时:

    1 Search Bar

    我的故事板:

    Storyboard edit 1

    最后我更新了视图控制器代码:

    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
    
        }
    }
    

    }

    我现在的问题是,只有第一个搜索栏是固定的,当我输入时它不会搜索。滚动时第二个搜索栏消失。此外,当我点击一个名称时,它不再会转到下一个视图。

4 个答案:

答案 0 :(得分:5)

问题是视图层次结构。

你的故事板是这样的:

enter image description here

在TableView上添加了搜索栏。

正确的等级是这样的:

enter image description here

您将UITableViewController更改为UIViewController,并附加SearchDisplayController,同时注意视图层次结构。

它会起作用:))

答案 1 :(得分:1)

iOS9

遇到同样的问题。我以编程方式添加了搜索栏。 这是我如何修复我的。未来可能会有所帮助:)

我在tableview&#39; viewForHeaderInSection上添加了 searchController.searchBar ,而不是添加到tableView.tableHeaderView

如果存在,请删除此行。 tableView.tableHeaderView = searchController.searchBar

然后在tableview的代表上实现这一点。

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
}

希望它有所帮助!

答案 2 :(得分:0)

我认为问题出现是因为您已将搜索栏添加为表标题视图。

tableView.tableHeaderView = searchController.searchBar

尝试在self.view中添加搜索栏,如下所示:

self.view.addSubview("Your search bar")

希望这能解决您的问题。

答案 3 :(得分:0)

您正在添加UISearchController UITableView headerView。表视图标题不是&#34; sticky&#34;,并在用户滚动表格时滚动单元格。考虑创建一个标题标题,并在UISearchController中添加viewForHeaderInSection