尝试在 Swift 中使用 UISearchResult。如何实现过滤?

Posted

技术标签:

【中文标题】尝试在 Swift 中使用 UISearchResult。如何实现过滤?【英文标题】:Trying to use UISearchResult in Swift. How to implement filtering? 【发布时间】:2016-04-06 10:30:00 【问题描述】:

我正在尝试在我的应用中创建露营地搜索功能。我希望用户能够在搜索栏中输入内容,并让显示的露营地过滤器列表与他们输入的内容相匹配。现在用户点击一个按钮来调出 SearchCampgroundsViewController.swift。这是我目前在该文件中的代码:

import UIKit

class SearchCampgroundsViewController: UIViewController, UISearchResultsUpdating 

    let searchController = UISearchController(searchResultsController: nil)

    @IBOutlet weak var tableView: UITableView!
    var campgrounds: [Campground]? 
       return DataProvider.sharedInstance.allCampground()
    


    override func viewDidLoad() 
        super.viewDidLoad()

        searchController.searchResultsUpdater = self
        searchController.hidesNavigationBarDuringPresentation = false
        searchController.dimsBackgroundDuringPresentation = false
        self.tableView.tableHeaderView = searchController.searchBar
    


    func updateSearchResultsForSearchController(searchController: UISearchController) 

    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    




extension SearchCampgroundsViewController: UITableViewDataSource 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return self.campgrounds?.count ?? 0
    

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCellWithIdentifier("campgroundCell")! as UITableViewCell
        cell.textLabel?.text = campgrounds?[indexPath.row].facilityName ?? "NO NAME FOR THIS FACILITY"
        return cell
    

露营地列表在表格视图中正确显示(列表长约 4000 项),并且搜索栏正确显示在表格顶部。我可以在搜索栏中输入,但结果没有过滤。如何实现过滤? updateSearchResultsForSearchController 函数需要做什么?

【问题讨论】:

【参考方案1】:

您需要使用在搜索栏中输入的文本 (searchController.searchBar.text) 过滤您的数据源 (campgrounds),然后使用过滤后的数据重新加载您的表格视图。

如果要将数据源保留为计算属性,则需要定义一个新变量来保存过滤后的露营地数组(见下文)。然后,您必须引入检查以确定使用哪个数据源,具体取决于搜索控制器是否处于活动状态。

或者,您可以使用单个数据源,它会根据需要返回一组过滤或未过滤的露营地。

请注意,您需要import Foundation 才能使用rangeOfString()

尝试以下方法:

import Foundation

/* ... */

var filtered: [Campground]?

func updateSearchResultsForSearchController(searchController: UISearchController)         
    filtered = campgrounds?.filter 
        // True if facilityName contains search bar text (case-sensitive).
        $0.facilityName.rangeOfString(searchController.searchBar.text!) != nil
    

    tableView.reloadData()


/* ... */

extension SearchCampgroundsViewController: UITableViewDataSource

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        if searchController.active && !searchController.searchBar.text.isEmpty 
            return filtered?.count ?? 0
        

        return campgrounds?.count ?? 0
    

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCellWithIdentifier("campgroundCell")! as UITableViewCell

        if searchController.active && searchController.searchBar.text != "" 
            cell.textLabel?.text = filtered?[indexPath.row].facilityName ?? "NO NAME FOR THIS FACILITY"
         else 
            cell.textLabel?.text = campgrounds?[indexPath.row].facilityName ?? "NO NAME FOR THIS FACILITY"
        

        return cell
    

【讨论】:

感谢您的回复。我实现了这段代码。它正在过滤,虽然不是很准确。例如,如果我键入“D”,它仍会在该列表顶部显示以 A 开头的项目。此外,当我单击搜索栏时,该列表会消失。代码的哪一部分控制这个? 重新准确性——示例代码中使用的过滤条件是设施名称是否包含搜索文本,而不是设施名称是否以搜索文本开头。如果您更喜欢后者,可以将rangeOfString() 替换为hasPrefix() 重新消失的列表——这可能是由示例代码中检查self.searchController.active 的部分控制的(只要你点击搜索栏就是这样)。我已经编辑了这些部分以添加检查以确保搜索栏文本不为空。这应该可以防止原始露营地列表消失,直到在搜索栏中输入一些文本。

以上是关于尝试在 Swift 中使用 UISearchResult。如何实现过滤?的主要内容,如果未能解决你的问题,请参考以下文章

尝试在 Swift 中使用来自 CKRecord 的原始数据形式

尝试在启动应用程序时使用 Swift 在 Xcode 中查找用户位置但出现可选错误?

尝试在具有 SpriteKit 场景 (SWIFT) 的 didMoveToView 中使用 waitForDuration 延迟生成节点但不工作

使用 MLKit ios swift 尝试化妆

在 Swift 2.0 中使用 NSFetchedResultsController

在 Swift 中解析和存储 JSON