Поле поиска и табличное представление - отображаются только пользователи с именами в верхнем регистре - PullRequest
0 голосов
/ 11 января 2019

В моем приложении есть поле поиска, где пользователи могут искать других пользователей. Однако у меня есть три проблемы с этим:

  1. сейчас поиск работает только для пользователей, которые имеют имя пользователя в верхнем регистре. Так, например, когда я ищу «Ма», единственный пользователь, который показывает это «Макелеле», потому что его имя пользователя имеет заглавную букву в качестве первой буквы. Например, "mattgilbert" вообще не отображается, хотя я должен быть на столе.

  2. когда пользователь появился в представлении таблицы, он все еще находится в представлении таблицы, даже если я отменил поиск.

  3. У меня это есть, поэтому поиск пользователей начинается только тогда, когда пользователь набрал как минимум 2 слова, однако, если пользователь вводит больше, чем это, в поле поиска, пользователь просто исчезнет в представлении таблицы. И мне нужно искать больше букв, чтобы пользователь появился снова.

Это бы много значило, если бы кто-то мог мне помочь в этом, так как я потратил много времени на поиск. Я хочу, чтобы он был как можно более экономичным и в то же время масштабируемым (поэтому я набираю эти две буквы как минимум до того, как база данных выполнит свой запрос)

Это мой код:

class FollowUsersTableViewController: UIViewController {

    @IBOutlet var tableView: UITableView!

    var isSearching = false

    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

        //self.loadProfileData()

       //self.searchBar(searchController.searchBar, textDidChange: searchController.searchBar.text)







    }





    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 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]

        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: isSearching ? self.filteredUsers[indexPath.row] : self.usersArray[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()))
            }
        }
    }


    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) {

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


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


}

РЕДАКТИРОВАТЬ: обновленный код

class FollowUsersTableViewController: UIViewController {

    @IBOutlet var tableView: UITableView!

    var isSearching = false

    private var viewIsHiddenObserver: NSKeyValueObservation?
    let searchController = UISearchController(searchResultsController: nil)
    var usersArray = [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

        //self.loadProfileData()

       //self.searchBar(searchController.searchBar, textDidChange: searchController.searchBar.text)



    }


    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 usersArray.count
    }

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

        let user = usersArray[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.usersArray[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()))
            }
        }
    }
  */

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

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

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {


        isSearching = false

        self.usersArray = []

        self.tableView.reloadData()
    }

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

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

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


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


}

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Ответ на вопрос № 1

1) сейчас поиск работает только для пользователей с заглавными буквами имя пользователя. Так, например, когда я ищу "Ма", единственный пользователь, который отображается «Макелеле», потому что его имя пользователя имеет заглавную букву как первая буква Например, "Mattgilbert" вообще не показывает, даже хотя я должен быть на столе.

Firebase не имеет поиска в верхнем или нижнем регистре. У него просто запрос строковой литералы, чувствительный к регистру

Типичное решение - сохранить «отображаемую» версию ваших строк, а затем «поисковую» версию ваших строк, в которой строка находится в нижнем регистре в коде перед сохранением в Firbease. Так, например, вот пользовательский узел

users
  uid_0
    display_name: "Kirk"
    search_name: "kirk"
  uid_1
    display_name: "Spock"
    search_name: "spock"
  uid_1
    display_name: "Montgomery Scott"
    search_name: "montgomery scott"

2, когда пользователь появился в виде таблицы, он все еще находится в tableview, хотя я отменил поиск.

Если поиск отменен, массив dataSource должен быть очищен, а ваш tableView перезагружен.

myDataSourceArray = [] 
self.reloadTableview

3 У меня это есть, поэтому поиск пользователей начинается только тогда, когда у пользователя есть набрал по крайней мере 2 слова, однако, если пользователь вводит больше, чем это в Поле поиска пользователь просто исчезнет в представлении таблицы. И я имею искать больше букв, чтобы пользователь снова появился.

Код, который я разместил в предыдущие ответы , решает эту проблему и представляет собой законченное, проверенное решение. Пожалуйста, вернитесь к этим ответам - вы можете почти скопировать и вставить код в проект, и он будет работать.

0 голосов
/ 11 января 2019

Пожалуйста, попробуйте это, возможно, вам поможет.

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    let filteredArray = usersArray.filter { ($0["username"] as! String).range(of: searchText!, options: [.diacriticInsensitive, .caseInsensitive]) != nil }
}

Это может вам помочь. Спасибо

...