使用 UISearchBar 文本搜索 UITableView 单元格

Posted

技术标签:

【中文标题】使用 UISearchBar 文本搜索 UITableView 单元格【英文标题】:Search UITableView cells using UISearchBar text 【发布时间】:2019-04-12 07:27:03 【问题描述】:

我想使用 UISearchBar 在UITableView 中显示过滤后的单元格,但它不起作用。我的搜索功能在我的代码末尾。


import UIKit

struct User2: Codable 
    let firstName: String
    let lastName: String
    let email: String
    let userid: String

    enum CodingKeys: String, CodingKey 
        case firstName = "first_name"
        case lastName = "last_name"
        case email = "email"
        case userid = "user_id"
    


class SearchViewController: UIViewController, UITableViewDataSource, UITableViewDelegate 

    @IBOutlet weak var tableview: UITableView!

    @IBOutlet var searchBtn: UISearchBar!
    private var dataSource = [User]() 
        didSet 
            self.tableview.reloadData()
        
    

    override func viewDidLoad() 
        super.viewDidLoad()

        self.tableview.register(UITableViewCell.self, forCellReuseIdentifier: "groupCell")
        self.tableview.dataSource = self
        self.tableview.delegate = self

        let url = URL(string: "https://ex.com/ex.php")

        URLSession.shared.dataTask(with: url!, completionHandler:  [weak self] (data, response, error) in
            guard let data = data, error == nil else 
                print(error?.localizedDescription ?? "An error occurred")
                return
            

            DispatchQueue.main.async 
                self?.dataSource = try! JSONDecoder().decode([User].self, from: data)
            
        ).resume()
    

    override func viewDidAppear(_ animated: Bool) 
        super.viewDidAppear(animated)
        tableview.reloadData()
    

    func numberOfSections(in tableView: UITableView) -> Int 
        return 1
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return dataSource.count
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "groupCell", for: indexPath)
        let user = self.dataSource[indexPath.row]
        cell.textLabel?.text =  user.firstName + " " + user.lastName

        return cell
    

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        let user = self.dataSource[indexPath.row]
        let userVC = DataViewController(user: user)
        self.navigationController?.pushViewController(userVC, animated: true)
    
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
        User2 = User2.filter( (item) -> Bool in
            let heading: NSString = ((item["firstName"]! as? String)! + (item["lastName"]! as! String)) as NSString
            return (heading.range(of: searchText, options: NSString.CompareOptions.caseInsensitive).location) != NSNotFound
        )
        self.tableview.reloadData()
    


【问题讨论】:

你的NSString - String 舞蹈太可怕了。您需要第二个数组用于搜索结果以保留整个原始数组。而且你不能过滤类型。 【参考方案1】:

更好的方法是拥有 2 个数据源,一个用于正常状态,另一个用于主动搜索,如下所示:

class SearchViewController: UIViewController, UITableViewDataSource, UITableViewDelegate 

    private var dataSource = [User]() 
        didSet 
            self.tableview.reloadData()
        
    

    private var searchDataSource: [User]? 
        didSet 
            self.tableView.reloadData()
        
    

    override func viewDidLoad() 
        super.viewDidLoad()

        ...
        self.searchBtn.delegate = self
    

    // some changes to UITableView DataSource/Delegate
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return self.searchDataSource?.count ?? self.dataSource.count
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        ...
        let user = self.searchDataSource?[indexPath.row] ?? self.dataSource[indexPath.row]
        ...
     


最后使用以下扩展名扩展UISearchBarDelegate

extension SearchViewController: UISearchBarDelegate 

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
        if searchText.isEmpty 
            self.searchDataSource = nil
         else 
            self.searchDataSource = self.dataSource.filter(
                let fullName = $0.firstName + " " + $0.lastName
                return fullName.range(of: searchText, options: [.anchored, .caseInsensitive]) != nil
            )
        
    

    func searchBarTextDidEndEditing(_ searchBar: UISearchBar) 
        if self.searchDataSource != nil && searchBar.text?.isEmpty ?? true 
            self.searchDataSource = nil
        
    


产生

【讨论】:

将此代码粘贴到我的应用程序@AamirR 时出现很多错误【参考方案2】:

我认为应该在dataSource 上应用过滤器,其中dataSource 类似于[User2]

    let filteredArr: [User] = dataSource.filter( $0.firstName.lowercased().contains(searchText.lowercased()) || $0.lastName.lowercased().contains(searchText.lowercased()) )

【讨论】:

【参考方案3】:

您可以尝试在dataSource 中应用过滤,例如:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
   let filteredArray = dataSource.filter( user in
   let username = "\(user.firstName) \(user.lastName)"
      return username.range(of: searchText, options: .caseInsensitive) != nil
   )
   self.tableview.reloadData()

【讨论】:

以上是关于使用 UISearchBar 文本搜索 UITableView 单元格的主要内容,如果未能解决你的问题,请参考以下文章

Swift iOS 8+ UISearchBar图标,占位符和文本居中

无论是不是有搜索文本匹配,UISearchBar 都显示“无结果”

使 UISearchBar 在两个不同的字段上进行搜索

Swift:UISearchBar:单击搜索按钮时获取文本

编辑搜索栏中的文本时出现 UISearchBar 问题

输入搜索栏文本框时出现 UISearchBar 错误