如何防止搜索栏在滚动时消失? iOS 斯威夫特

Posted

技术标签:

【中文标题】如何防止搜索栏在滚动时消失? iOS 斯威夫特【英文标题】:How to prevent search bar from disappearing on scroll? iOS Swift 【发布时间】:2015-07-29 13:49:44 【问题描述】:

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

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

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

这是我的故事板的图片:

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

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 的解决方案采取的步骤:

    Command X 表格视图。 添加视图。 Command V 将表格视图转换为新视图。 在视图控制器中,将 UITableViewController 更改为 UITableView 向视图控制器添加一个名为 table view 的 outlet。 删除表视图函数中的覆盖。 去掉这行代码:tableView.tableHeaderView = searchController.searchBar 返回故事板并将搜索栏移出表格视图。它会出现在表格视图的后面。 向下移动表格视图并向上移动搜索栏。 添加必要的约束。

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

当我向下滚动时:

我的故事板:

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

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

    

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

【问题讨论】:

这个问题可能重复:***.com/questions/24796274/… 【参考方案1】:

问题是视图层次结构。

你的故事板是这样的:

在 TableView 上添加了搜索栏。

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

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

它会起作用的:)

【讨论】:

Ryosuke Hiramastsu 好的,我已经很接近了。我的层次结构和你的一样,我将 UITableViewController 更改为 UIViewController,并使用 tableView.tableHeaderView = searchController.searchBar 来附加我的 searchController。页面顶部有一个搜索栏,表格视图中有一个搜索栏。第一个搜索栏是静止的,不会移动,但第二个搜索栏在滚动时移动。如果我尝试使用固定搜索栏进行搜索,它将不起作用。我该如何解决?我更新了我原来的帖子。请在 EDIT 1 下查看。 @2015HuntMJ 好的,你应该删除tableView.tableHeaderView = searchController.searchBar @Ryousuke Hiramastsu 我删除了那行代码,第二个搜索栏不见了。固定搜索栏停留在页面顶部,但是当我尝试输入它时,它似乎没有连接到表格视图并且没有搜索。我删除的第二个搜索栏进行了搜索。 @2015HuntMJ 接下来,你从 故事板作为 IBOutlet 创建searchController。 u 将storyboars的searchDisplayController连接到代码,删除3行:var searchController:UISearchController!searchController.searchResultsUpdater = selfsearchController.dimsBackgroundDuringPresentation = false @Ryousuke Hiramastsu 好吧,我从情节提要中创建了 searchController 作为出口并将其连接到代码。然后我删除了那三行代码。【参考方案2】:

您正在添加一个UISearchController 作为您的UITableViewheaderView。表格视图标题不是“粘性的”,并且在用户滚动表格时与单元格一起滚动。考虑创建一个部分标题并将您的UISearchController 添加到viewForHeaderInSection

【讨论】:

【参考方案3】:

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

希望对你有帮助!

【讨论】:

你好。在你的例子中,当我按下一个按钮(让我们说“d”)时,键盘会掉下来,我无法从搜索栏中按下“取消”......你知道为什么吗?【参考方案4】:

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

tableView.tableHeaderView = searchController.searchBar

尝试像这样在 self.view 中添加搜索栏:

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

希望这能解决您的问题。

【讨论】:

以上是关于如何防止搜索栏在滚动时消失? iOS 斯威夫特的主要内容,如果未能解决你的问题,请参考以下文章

导航栏在搜索结果表视图中消失

UISearchBar 不在 TableViewController 的表视图标题中?

防止 Chrome 浏览器地址栏在 iOS 设备中自动隐藏

在 iOS 11 上以编程方式滚动 UISearchController 的搜索栏不会消失

搜索栏在 iOS 中无法正常工作 [关闭]

如何让导航栏在滚动到设定点后松开?