ios - 在从 Firebase DB 获取结果的 UITableView 上实现搜索
问题描述
我有一个UITableView
从 Firebase 实时数据库获取数据的设备。我需要添加对列表的搜索,获取的数据属于名为Post
. 一旦用户单击单元格,它将数据传递给详细视图控制器。搜索目前无法正常工作,因为它正在搜索 aNSDictionary
而不是Post
,我也不确定如何去做。
class PostTable: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
filterContentForSearchText(searchController.searchBar.text!)
print(searchController.searchBar.text)
}
func searchBarIsEmpty() -> Bool {
// Returns true if the text is empty or nil
return searchController.searchBar.text?.isEmpty ?? true
}
func filterContentForSearchText(_ searchText: String) {
print("Search Text = " + searchText)
filteredPosts = filteredPosts.filter({( post : Post) -> Bool in
print(post.title.title.lowercased().contains(searchText.lowercased()))
return post.title.title.lowercased().contains(searchText.lowercased())
})
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
cell.set(post: posts[indexPath.row])
let user : Post
if searchController.isActive && searchController.searchBar.text != "" {
user = filteredPosts[indexPath.row]
}
else
{
cell.set(post: posts[indexPath.row])
}
return cell
}
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var tableView: UITableView!
var searchActive : Bool = false
let searchController = UISearchController(searchResultsController: nil)
var posts = [Post]()
var filteredPosts = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
if Auth.auth().currentUser == nil {
switchStoryboard()
}
let cellNib = UINib(nibName: "PostTableViewCell", bundle: nil)
tableView.register(cellNib, forCellReuseIdentifier: "postCell")
var layoutGuide:UILayoutGuide!
tableView.delegate = self
tableView.dataSource = self
tableView.tableFooterView = UIView()
tableView.reloadData()
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
observePosts()
}
func switchStoryboard() {
DispatchQueue.main.async {
let vc: UIViewController? = self.storyboard?.instantiateViewController(withIdentifier: "ViewController")
var window: UIWindow? = (UIApplication.shared.delegate?.window)!
window?.rootViewController = vc
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func observePosts() {
let postsRef = Database.database().reference().child("Data").queryOrdered(byChild: "priority")
print(postsRef)
postsRef.observe(.value, with: { snapshot in
var tempPosts = [Post]()
for child in snapshot.children{
if let childSnapshot = child as? DataSnapshot,
let dict = childSnapshot.value as? [String:Any],
let title = dict["title"] as? String,
let logoImage = dict["image"] as? String,
let url = URL(string:logoImage),
let address = dict["address"] as? String,
let contact = dict["contact"] as? String,
let description = dict["description"] as? String{
let userProfile = UserProfile(title: title, photoURL: url)
let post = Post(id: childSnapshot.key, title: userProfile, description: description, image: userProfile, address: address, contact: contact)
print(post)
tempPosts.append(post)
}
}
self.posts = tempPosts
self.tableView.reloadData()
})
}
func getImage(url: String, completion: @escaping (UIImage?) -> ()) {
URLSession.shared.dataTask(with: URL(string: url)!) { data, response, error in
if error == nil {
completion(UIImage(data: data!))
} else {
completion(nil)
}
}.resume()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.isActive && searchController.searchBar.text != ""{
return filteredPosts.count
} else {
return posts.count
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let postsInfo = posts[indexPath.row]
print(postsInfo)
let Storyboard = UIStoryboard(name: "Main", bundle: nil)
let DvC = Storyboard.instantiateViewController(withIdentifier: "PostTableDetailed") as! PostTableDetailed
DvC.getName = postsInfo.title.title
DvC.getDesc = postsInfo.description
DvC.getImg = postsInfo.title.photoURL.absoluteString
DvC.getAddress = postsInfo.address
DvC.getContact = postsInfo.contact
self.navigationController?.pushViewController(DvC, animated: true)
}
}
解决方案
cellForRow
是错的
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
let post = searchController.isActive ? filteredPosts[indexPath.row] : posts[indexPath.row]
cell.set(post: post)
return cell
}
检查就足够了searchController.isActive
。
而且你必须过滤posts
不filteredPosts
。我还更改了的签名filterContentForSearchText
以符合命名准则。
func filterContent(for searchText: String) {
filteredPosts = posts.filter{ $0.title.range(of: searchText, options: .caseInsensitive) != nil }
tableView.reloadData()
}
请注意,didSelectRowAt
当它处于活动状态时可能会崩溃或导致意外行为searchController
。
推荐阅读
- xcode - 使用 SwiftUi 为 Apple Watch 构建一个基本的高度计
- c++ - clang 10 & OpenMP on range-based for error(文档说应该没问题)
- c# - 在 Windows 服务中监控正在运行的进程调试信息
- javascript - 通过拖放项目创建数组
- c++ - 将头文件添加到 g++ 编译器的路径
- html - CSS将绝对对齐到列表项
- java - 如何在 JAVA 中以字符串数组为主体向其发出 HttpPut 请求?
- amazon-web-services - AWS-S3:分段上传如何提高吞吐量
- url-routing - Blazor 检索相对 url
- powershell - 递归计算文件夹中的文件并输出到文件