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

How to prevent search bar from disappearing on scroll? iOS Swift

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

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

如何防止搜索栏在滚动时消失?我希望它像第一张图片一样始终位于页面顶部。

这是我的故事板的图片:

如果解决方案不在情节提要中,这是我的视图控制器代码:

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() { [=12=].name < .name }

        //remove contacts whose locations are nil
        contacts = contacts.filter() { [=12=].location != "nil"}

        //remove contacts whose titles phone email and department are all nil
        contacts = contacts.filter() {
            if([=12=].title != "" || [=12=].phone != "" || [=12=].email != "" || [=12=].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 table 视图。
  2. 添加视图。
  3. 命令V table视图进入新视图。
  4. 在视图控制器中,将 UITableViewController 更改为 UITableView
  5. 向名为 table 视图的视图控制器添加一个出口。
  6. 删除 table 视图函数中的覆盖。
  7. 删除这行代码:tableView.tableHeaderView = searchController.searchBar
  8. 返回故事板并将搜索栏移出 table 视图。它会出现在 table 视图后面。
  9. 向下移动 table 视图,向上移动搜索栏。
  10. 添加必要的约束条件。

我的视图现在看起来像这样:

当我向下滚动时:

我的故事板:

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

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() { [=13=].name < .name }

    //remove contacts whose locations are nil
    contacts = contacts.filter() { [=13=].location != "nil"}

    //remove contacts whose titles phone email and department are all nil
    contacts = contacts.filter() {
        if([=13=].title != "" || [=13=].phone != "" || [=13=].email != "" || [=13=].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

    }
}

}

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

问题是视图层次结构。

你的故事板是这样的:

在 TableView 上添加了搜索栏。

正确的层次结构是这样的:

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

它会起作用:)

我认为出现问题是因为您将搜索栏添加为 table header 视图。

tableView.tableHeaderView = searchController.searchBar

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

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

希望这能解决您的问题。

您正在添加 UISearchController 作为 UITableViewheaderView。 Table 视图 header 不是 "sticky",并且当用户滚动浏览 table 时与单元格一起滚动。考虑创建一个部分 header 并在 viewForHeaderInSection.

中添加您的 UISearchController

iOS9

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

我在 tableview 的 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
}

希望对您有所帮助!