为什么不发送我的 tableview 显示搜索结果?
Why dosent my tableview show search results?
我试图仅在用户输入至少 2 个单词时完成对其他用户的搜索,然后才开始在数据库中搜索(因为我不想为用户扫描整个数据库).我在搜索 2 个字母时遇到了一些问题,但我想我得到了代码(感谢用户 Jay)。
然而,当我在模拟器中 运行 时,控制台打印名称,但在 tableview 中什么也没有显示? (它是空的)。
你知道我做错了什么吗?
这是我的代码:
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()))
}
}
}
}
您有 2 个数组 usersArray
和 filteredUsers
if childSnap.key != self.loggedInUser?.uid { //ignore this user
self.usersArray.append(userObj!)
}
...
self.tableView.reloadData()
所以上面的重新加载没有效果,因为你一直在使用
let user = filteredUsers[indexPath.row]
in cellForRowAt
,在这种情况下你应该有一个像
这样的变量
var isSearching = false
然后在所有委托和数据源方法中搜索时更改它
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])
}
这段代码非常接近,正如另一个答案指出的那样,您有两个数组。
但让我们真正简化问题:您只需要一个数组,因为您过滤的是 Firebase,而不是数组。
换句话说,当用户在 searchField 中键入内容时,您正在向 Firebase 查询结果并将它们放入一个数组中。 那是您应该用作 tableView 的数据源的同一个数组。
当您的代码运行时,您正在过滤 Firebase,然后再次过滤那些不需要的结果。
所以在高层次上假设我们的数据库中有四个用户
Larry
Moe
Monroe
Curly
用户在搜索字段中键入 'Mo',这会导致您的 Fire 查询执行。它将return两个结果:
Mo
Monroe
然后填充到数组中 - 我们将其称为 userResultsArray。
然后
tableView.reloadData()
然后调用 tableView 委托方法
func tableView(_ tableView: UITableView, numberOfRowsInSection
return userResultsArray.count
和
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
get the user from userResultsArray
return the user name
如图所示,您只需要一个数组来存储来自 Firebase 的查询(过滤)结果。
我试图仅在用户输入至少 2 个单词时完成对其他用户的搜索,然后才开始在数据库中搜索(因为我不想为用户扫描整个数据库).我在搜索 2 个字母时遇到了一些问题,但我想我得到了代码(感谢用户 Jay)。
然而,当我在模拟器中 运行 时,控制台打印名称,但在 tableview 中什么也没有显示? (它是空的)。
你知道我做错了什么吗?
这是我的代码:
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()))
}
}
}
}
您有 2 个数组 usersArray
和 filteredUsers
if childSnap.key != self.loggedInUser?.uid { //ignore this user
self.usersArray.append(userObj!)
}
...
self.tableView.reloadData()
所以上面的重新加载没有效果,因为你一直在使用
let user = filteredUsers[indexPath.row]
in cellForRowAt
,在这种情况下你应该有一个像
var isSearching = false
然后在所有委托和数据源方法中搜索时更改它
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])
}
这段代码非常接近,正如另一个答案指出的那样,您有两个数组。
但让我们真正简化问题:您只需要一个数组,因为您过滤的是 Firebase,而不是数组。
换句话说,当用户在 searchField 中键入内容时,您正在向 Firebase 查询结果并将它们放入一个数组中。 那是您应该用作 tableView 的数据源的同一个数组。
当您的代码运行时,您正在过滤 Firebase,然后再次过滤那些不需要的结果。
所以在高层次上假设我们的数据库中有四个用户
Larry
Moe
Monroe
Curly
用户在搜索字段中键入 'Mo',这会导致您的 Fire 查询执行。它将return两个结果:
Mo
Monroe
然后填充到数组中 - 我们将其称为 userResultsArray。
然后
tableView.reloadData()
然后调用 tableView 委托方法
func tableView(_ tableView: UITableView, numberOfRowsInSection
return userResultsArray.count
和
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
get the user from userResultsArray
return the user name
如图所示,您只需要一个数组来存储来自 Firebase 的查询(过滤)结果。