UISearchBar не ищет информацию в TableView - PullRequest
0 голосов
/ 07 июня 2019

Я пытаюсь получить данные из firebase и показать в tableView. Все хорошо. Но мне нужно искать в tableView, используя UISearchBar. Я должен решить две проблемы.

1) Когда я начинаю печатать, мой tableView исчезает. вся информация в нем не отображается

2) Когда я стираю все в UISearchBar, ничего не появляется.

import UIKit
import SPStorkController
import Firebase

class FoodViewController: UIViewController {

    override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }
    let tableView = UITableView()
    var foods = [FoodModel]()
    var searchedFoods = [String]()
    var searching = false

    override func viewDidLoad() {
        super.viewDidLoad()

        fetchFoods()

        self.modalPresentationCapturesStatusBarAppearance = true
        self.view.backgroundColor = UIColor.white
        let controller = UIViewController()

        self.tableView.delegate = self
        self.tableView.dataSource = self
        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")            

        self.view.addSubview(self.tableView)

        tableView.delegate = self
        tableView.dataSource = self

        let searchBar = UISearchBar(frame: CGRect(x: 0, y: 5, width: 350, height: 40))
        searchBar.searchBarStyle = .minimal
        searchBar.delegate = self

        self.view.addSubview(searchBar)            
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        self.updateLayout(with: self.view.frame.size)
    }

    func updateLayout(with size: CGSize) {
        self.tableView.frame = CGRect.init(x: 0, y: 45, width: size.width, height: 400)            
    }

    func fetchFoods() {
        Database.database().reference().child("food").observe(.childAdded) { (snapshot) in
            if let dict = snapshot.value as? [String: AnyObject] {
                let newTitle = dict["title"] as! String
                let exCell = FoodModel(title: newTitle)
                self.foods.append(exCell)
                DispatchQueue.main.async {
                    self.tableView.reloadData()                        
                }
            }                
        }            
    }
}

extension FoodViewController: UITableViewDataSource { 

   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        if searching {
            cell.textLabel?.text = searchedFoods[indexPath.row]
        } else {
            let food = foods[indexPath.item]
            cell.textLabel?.text = food.title
        }
        return cell
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searching {
            return searchedFoods.count
        } else {
            return foods.count
        }
    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    }
}

extension FoodViewController: UITableViewDelegate {

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView == self.tableView {
            SPStorkController.scrollViewDidScroll(scrollView)
        }
    }
}

extension FoodViewController: UISearchBarDelegate {

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        //searchedFoods = foods.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
        searching = true
        tableView.reloadData()
    }

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searching = false
        searchBar.text = ""
        tableView.reloadData()
    }        
}`

Это моя модель

class FoodModel {

    var title = String()

    init (title: String) {

        self.title = title
    }
}

Ответы [ 2 ]

1 голос
/ 07 июня 2019

Вы должны разделить массив источника данных и фильтрованный массив с одним и тем же типом

var searchedfoods = [FoodModel]()

, и вам необходимо реализовать textDidChange таким образом, он отменяет поиск, если текст поиска пуст

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText.isEmpty {
        searchedFoods.removeAll()
        searching = false
    } else {
        searchedFoods = foods.filter{ $0.title.range(of: searchText, options: [.caseInsensitive, .anchored]) != nil }
        searching = true
    }
    tableView.reloadData()
}

Ваш API для фильтрации предметов очень громоздок и излишне дорог.range(of:options: указание соответствующих опций намного эффективнее.caseInsensitive позволяет избежать множественных вызовов lowercased() и .anchored поиска всегда с начала строки.

1 голос
/ 07 июня 2019

searchedFoods должен быть массивом объектов, таким же, как основной список продуктов.

Я думаю, вам просто нужно обновить свою фильтрацию

, поэтому измените searchedFoods на [FoodModel]()

, а затем измените фильтр на это:

searchedFoods = foods.filter({ $0.title.lowercased().prefix(searchText.count) == searchText.lowercased() })
...