使用UISearchBar文本搜索UITableView单元格

时间:2019-04-12 07:27:04

标签: json swift uitableview uisearchbar

我想使用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()
    }

}

3 个答案:

答案 0 :(得分: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
        }
    }

}

可以产生

enter image description here

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

您可以尝试在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()
}