iOS开发求助:TableView无法显示搜索结果问题排查
Hey there! Let's break down why your TableView stays empty even though the console is printing usernames. The core problem boils down to async data timing and how you're handling your user arrays. Here's what's going wrong, plus fixes you can implement:
1. Async Data Loading & Filtering Order is Broken
Your searchUsers method uses Firebase's asynchronous observeSingleEvent call—meaning it doesn't populate usersArray immediately. But in updateSearchResults, you call searchUsers and then immediately run filterContent and reload the TableView. At that point, the Firebase callback hasn't finished, so usersArray is still empty, and filteredUsers ends up empty too.
Fix: Move Filtering & Reload to the Firebase Callback
Update your searchUsers method to run filtering only after the data is loaded from Firebase:
func searchUsers(text: String) { guard text.count >= 2 else { self.usersArray = [] self.filteredUsers = [] self.tableView.reloadData() return } self.usersArray = [] // Clear array before new search 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) // Safely unwrap the mapped user object to avoid crashes if let userObj = Mapper<UserModel>().map(JSONObject: childSnap.value!) { userObj.uid = childSnap.key // Skip the logged-in user if childSnap.key != self.loggedInUser?.uid { self.usersArray.append(userObj) } } } // Now that we have data, filter it and refresh the table self.filterContent(searchText: text) self.tableView.reloadData() }) }
2. Simplify updateSearchResults
Since we're now handling filtering and reloading inside the Firebase callback, you can strip down your updateSearchResults method to just trigger the search:
func updateSearchResults(for searchController: UISearchController) { searchController.searchResultsController?.view.isHidden = false guard let searchText = searchController.searchBar.text else { return } self.searchUsers(text: searchText) }
3. Fix Minor Edge Cases in Filtering & Row Count
- Optional Safety: Add guards in
filterContentto avoid crashes if a user has no username:func filterContent(searchText: String){ guard searchText.count >= 2 else { self.filteredUsers = [] return } self.filteredUsers = self.usersArray.filter{ user in guard let username = user.username else { return false } return username.lowercased().contains(searchText.lowercased()) } } - Row Count Safety: Update
numberOfRowsInSectionto safely handle empty or nil search text:func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { guard let searchText = searchController.searchBar.text, searchText.count >= 2 else { return 0 } return filteredUsers.count }
4. Double-Check databaseRef Initialization
You commented out the databaseRef declaration—make sure it's properly initialized in your class to avoid silent failures:
private let databaseRef = Database.database().reference()
Why This Works
By moving the filtering and TableView reload into the Firebase callback, we ensure we only work with data after it's actually been loaded from the database. This fixes the timing issue that was leaving filteredUsers empty when the TableView tried to populate itself.
内容的提问来源于stack exchange,提问作者Matt Gilbert

