简体   繁体   中英

Swift search bar - updating table view with Alamofire request

I've made up some string search on my database and i return the JSON after the user pushes the 3rd character on search bar, after that I append all the results to an Array and it fills a tableview with data.

Although I'm dealing with an issue. When I search lets say for mens I get the results appear on the tableview

If i delete all the text and i write women, all good... but when i'm deleting some strings etc i get an error index out of range inside the tableview cellForRowAt. I guess that it breaks cause the tableview doesn't have the time to get the appended array and fill the cells.

What I'm trying to find out is how can i make it work, WITHOUT setting a time delay on the query or in the reloadData() . The reason I don't want time delay is because some user's might have a slow - old iPhone and even with 2 sec delay, it could crash.

This is my code

class SearchViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UISearchControllerDelegate{

@IBOutlet weak var searchResultTable: UITableView!
    let searchController = UISearchController(searchResultsController: nil)

    var filteredData = [Products]()

override func viewDidLoad() {
        super.viewDidLoad()


        self.navigationController?.isNavigationBarHidden = true
        searchController.searchResultsUpdater = self
        searchController.dimsBackgroundDuringPresentation = false
        definesPresentationContext = true
        searchResultTable.tableHeaderView = searchController.searchBar

        searchController.searchBar.delegate = self

    }


func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
        searchBar.resignFirstResponder()
    }


    func getSearch(completed: @escaping DownloadComplete, searchString: String) {
        if filteredData.isEmpty == false {
            filteredData.removeAll()
        }
        let parameters: Parameters = [
            "action" : "search",
            "subaction" : "get",
            "product_name"  : searchString,
            "limit" : "0,30"
        ]


        Alamofire.request(baseurl, method: .get, parameters: parameters).responseJSON { (responseData) -> Void in
            if((responseData.result.value) != nil) {
                let result = responseData.result

                if let dict = result.value as? Dictionary<String, AnyObject>{
                    if let list = dict["product_details"] as? [Dictionary<String, AnyObject>] {

                        for obj in list {
                            let manPerfumes = Products(productDict: obj)
                            self.filteredData.append(manPerfumes)
                        }


                    }
                }
                completed()
            }
        }
    }


func numberOfSections(in tableView: UITableView) -> Int {

        return 1

    }
    func tableView(_ tableView: UITableView,
                   heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 170
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return filteredData.count
    }

    func tableView(_ tableView: UITableView,
                   cellForRowAt indexPath: IndexPath) -> UITableViewCell {

            let cell:iPhoneTableViewCell = tableView.dequeueReusableCell(withIdentifier: "iPhoneTableCell", for: indexPath) as! iPhoneTableViewCell

            let prods = self.filteredData[indexPath.row] //HERE I GET THE ERROR
            cell.configureCell(products: prods)

            return cell

    }

}

extension SearchViewController: UISearchResultsUpdating {

    func updateSearchResults(for searchController: UISearchController) {

        if (searchController.searchBar.text?.characters.count)! >= 3 {
                    self.getSearch(completed: {
                    self.searchResultTable.reloadData()

                    self.searchResultTable.setContentOffset(CGPoint.zero, animated: true)
                }, searchString: searchController.searchBar.text!)
        } else {
            self.searchResultTable.reloadData()
        }


    }
}

It looks like you are changing the state of filteredData while the tableView does reloadData . If numberOfRowsForSection returns 3, and then the user hits the delete key for example, the array size will become 0. That may be why cellForRow throws an exception when requesting indices 0,1 or 2.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM