Why dosent my tableview show search results?

跟風遠走 提交于 2019-12-13 08:10:47

问题


I'm trying to accomplish searching for other users only when the user has typed at least 2 words, and only then begin the search in the database (because I don't want to scan the entire database for the users). I had some problems with 2 letter search, but I think I got the code (thanks to user Jay).

However when I run it in the simulator, the console prints name, but nothing shows up in the tableview? (its empty).

Do you know what I have done wrong?

This is my code:

class FollowUsersTableViewController: UIViewController {

    @IBOutlet var tableView: UITableView!

    private var viewIsHiddenObserver: NSKeyValueObservation?
    let searchController = UISearchController(searchResultsController: nil)
    var usersArray = [UserModel]()
    var filteredUsers = [UserModel]()
    var loggedInUser: User?
    //
    var databaseRef = Database.database().reference()
    //usikker på den koden over

    override func viewDidLoad() {

        super.viewDidLoad()

        searchController.searchBar.delegate = self


        //large title
        self.title = "Discover"
        if #available(iOS 11.0, *) {
            self.navigationController?.navigationBar.prefersLargeTitles = true
        } else {
            // Fallback on earlier versions
        }

        self.tableView?.delegate = self
        self.tableView?.dataSource = self
        searchController.searchResultsUpdater = self
        searchController.dimsBackgroundDuringPresentation = false
        self.searchController.delegate = self;



        definesPresentationContext = true
        tableView.tableHeaderView = searchController.searchBar



    }

    func searchUsers(text: String) {
        if text.count >= 2 {
            self.usersArray = [] //clear the array each time
            let endingText = text + "\u{f8ff}"
            databaseRef.child("profile").queryOrdered(byChild: "username")
                .queryStarting(atValue: text)
                .queryEnding(atValue: endingText)
                .observeSingleEvent(of: .value, with: { snapshot in

                    for child in snapshot.children {
                        let childSnap = child as! DataSnapshot
                        print(childSnap)
                        let userObj =  Mapper<UserModel>().map(JSONObject: childSnap.value!)
                        userObj?.uid = childSnap.key
                        if childSnap.key != self.loggedInUser?.uid { //ignore this user
                            self.usersArray.append(userObj!)

                        }
                    }
                    self.tableView.reloadData()
                })
        }
    } //may need an else statement here to clear the array when there is no text


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let dest = segue.destination as! UserProfileViewController
        let obj = sender as! UserModel
        let dict = ["uid": obj.uid!, "username": obj.username!, "photoURL": obj.photoURL, "bio": obj.bio]
        dest.selectedUser = dict as [String : Any]
    }





}

// MARK: - tableview methods
extension FollowUsersTableViewController: UITableViewDataSource, UITableViewDelegate {



    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return searchController.searchBar.text!.count >= 2 ? filteredUsers.count : 0
    }

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

        let user = filteredUsers[indexPath.row]

        cell.title?.text = user.username
        if let url = URL(string: user.photoURL ?? "") {
            cell.userImage?.sd_setImage(with: url, placeholderImage: #imageLiteral(resourceName: "user_male"), options: .progressiveDownload, completed: nil)
            cell.userImage.sd_setIndicatorStyle(.gray)
            cell.userImage.sd_showActivityIndicatorView()
        }

        return cell
    }

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

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.performSegue(withIdentifier: "user", sender: self.filteredUsers[indexPath.row])
    }



}

// MARK: - search methods
extension FollowUsersTableViewController:UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate {



    func updateSearchResults(for searchController: UISearchController) {
        searchController.searchResultsController?.view.isHidden = false

        self.searchUsers(text: self.searchController.searchBar.text!)

        filterContent(searchText: self.searchController.searchBar.text!)

        self.tableView.reloadData()
    }

    func filterContent(searchText:String){

        if searchText.count >= 2{


            self.filteredUsers = self.usersArray.filter{ user in
                return(user.username!.lowercased().contains(searchText.lowercased()))
            }
        }
    }


}

回答1:


You have 2 arrays usersArray and filteredUsers

if childSnap.key != self.loggedInUser?.uid { //ignore this user
       self.usersArray.append(userObj!)
}
...
 self.tableView.reloadData()

so the the above reload has no effect as you always use

let user = filteredUsers[indexPath.row]

in cellForRowAt , in such cases you should have a var like

var isSearching = false

and alter it when you search then in all delegate & dataSource methods

 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return isSearching ? filteredUsers.count : usersArray.count
 }
 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! FollowTableViewCell

    let user = isSearching ? filteredUsers[indexPath.row] : usersArray[indexPath.row] 
  .....
 }

func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
    isSearching = true
}

func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    isSearching = false
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    isSearching = false
}

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    isSearching = false
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    filteredUsers = usersArray.filter { /* do filter */ }

    if(filteredUsers.count == 0){
        isSearching = false
    } else {
        isSearching = true
    }
    self.tableView.reloadData()
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    self.performSegue(withIdentifier: "user", sender: isSearching ? self.filteredUsers[indexPath.row] : self.usersArray[indexPath.row])
}



回答2:


This code is very close, and as the other answer points out you've got two arrays.

But let's really simplify the issue: You only need one array since you are filtering Firebase, not the array.

In other words when a user types into the searchField, you're querying Firebase for results and putting them into an array. That's the same array you should be using as the dataSource for your tableView.

As your code sits, you're filtering Firebase and then filtering those results again which isn't needed.

So at a high level supposed we have four users in our database

Larry
Moe
Monroe
Curly

the user types 'Mo' into the search field which causes your Fire query to execute. It will return two results:

Mo
Monroe

which then gets populated into an array - we'll call it userResultsArray.

then

tableView.reloadData()

which then calls the tableView delegate methods

func tableView(_ tableView: UITableView, numberOfRowsInSection
   return userResultsArray.count

and

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
   get the user from userResultsArray
   return the user name

As shown, you only need the single array to store the queried (filtered) results from Firebase.



来源:https://stackoverflow.com/questions/54111912/why-dosent-my-tableview-show-search-results

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!