【问题标题】:How do you search through firebase data in tableview with a SearchBar?如何使用 SearchBar 在 tableview 中搜索 firebase 数据?
【发布时间】:2020-08-15 23:36:21
【问题描述】:

我已经设置了一个 tableview,它从 firebase 实时数据库中检索数据,并将这些数据存储在一个数组('posts')中,格式如下:

(姓名:nil,contactEmail:可选(“35345345235”),contactPhoneNum:可选(“contact@gmail.com”),年龄:可选(“25”),性别:nil,lastSeen:nil, profileDescription: nil)

我想实现一个搜索栏来过滤帖子的名称值并在tableview中返回包含搜索名称的帖子,但不知道该怎么做。

这是我的代码:

import UIKit
import Firebase
import FirebaseDatabase
import SwiftKeychainWrapper
import FirebaseAuth

class FeedVC: UITableViewController, UISearchBarDelegate{
    
    @IBOutlet weak var searchBar: UISearchBar!
    
    var currentUserImageUrl: String!
    var posts = [postStruct]()
    var selectedPost: Post!
    var filteredPosts = [postStruct]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        getUsersData()
        getPosts()
        searchBar.delegate = self
        // Do any additional setup after loading the view.
   //     tableView.register(PostCell.self, forCellReuseIdentifier: "PostCell")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    
    func getUsersData(){

        guard let userID = Auth.auth().currentUser?.uid else { return }
        Database.database().reference().child("users").child(userID).observeSingleEvent(of: .value) { (snapshot) in
            if let postDict = snapshot.value as? [String : AnyObject] {
                self.tableView.reloadData()
            }
        }
    }
    
    struct postStruct {
        let name : String!
        let contactEmail : String!
        let contactPhoneNum : String!
        let age : String!
        let gender : String!
        let lastSeen : String!
        let profileDescription : String!
    }
    
    func getPosts() {
        let databaseRef = Database.database().reference()
        databaseRef.child("firstName").queryOrderedByKey().observe( .childAdded, with: {
                    snapshot in
                    let name = (snapshot.value as? NSDictionary)!["name"] as? String
                    let contactEmail = (snapshot.value as? NSDictionary
                    )!["contactEmail"] as? String
                    let contactPhoneNum = (snapshot.value as? NSDictionary
                    )!["contactPhoneNum"] as? String
                    let age = (snapshot.value as? NSDictionary
                    )!["age"] as? String
                    let gender = (snapshot.value as? NSDictionary
                    )!["gender"] as? String
                    let lastSeen = (snapshot.value as? NSDictionary
                    )!["lastSeen"] as? String
                    let profileDescription = (snapshot.value as? NSDictionary
                    )!["profileDescription"] as? String
            self.posts.append(postStruct(name: name,contactEmail:contactEmail, contactPhoneNum:contactPhoneNum, age:age, gender:gender, lastSeen:lastSeen, profileDescription:profileDescription))
            DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }
                })
    }
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        print("posts count = ", filteredPosts.count)
        return filteredPosts.count

   }
    
    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
      //  tableView.dequeueReusableCell(withIdentifier: "PostCell")!.frame.size.height
        return 230
    }
   override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell") as? PostCell else { return UITableViewCell() }
    cell.nameLabel?.text = filteredPosts[indexPath.row].name
        cell.contactEmailLabel?.text = filteredPosts[indexPath.row].contactEmail
        cell.contactPhoneNumLabel?.text = filteredPosts[indexPath.row].contactPhoneNum
        cell.ageLabel?.text = filteredPosts[indexPath.row].age
        cell.genderLabel?.text = filteredPosts[indexPath.row].gender
        cell.lastSeenLabel?.text = filteredPosts[indexPath.row].lastSeen
        cell.profileDescriptionLabel?.text = filteredPosts[indexPath.row].profileDescription
        print(filteredPosts)
        return cell
    }
    
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
          filteredPosts = posts.filter { $0.name?.lowercased().contains(searchText.lowercased()) == true }
}


}

【问题讨论】:

  • 需要澄清一下;您是否想将每个帖子 + 数据从 Firebase 加载到内存中,并将它们全部存储在一个数组中,然后对其进行过滤?还是您想查询 firebase 的数据并仅返回该数据子集?重要的是,如果您有一百万个帖子,您将压倒加载所有这些内容的设备。此外,您的数组是否仅包含“名称”(如在字符串中)还是包含整个“帖子”?
  • 对不起,我对 firebase 很陌生。我想搜索每个帖子的“名称”以返回匹配的名称,所以我不确定采用哪种方法。 'posts' 数组包含存储为 postStruct 的整个帖子数据(格式如上所示)。
  • 您需要做出决定,因为方法非常不同。如果您有很多帖子,如前所述,它可能会使设备不堪重负,但如果您正在查询 firebase,您只想返回一部分数据。
  • 这不是一个真正的坏问题 - 如果 OP 正在搜索和数组或 Firebase,则需要一些明确性。投票重新开放
  • 我最好在 firebase 中查询名称

标签: ios swift firebase tableview searchbar


【解决方案1】:

遍历posts 将提供Post 类型的元素,而不是String。这是修复:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    filteredPosts = []
    for post in posts {
        if post.name?.lowercased().contains(searchText.lowercased()) == true {
            filteredPosts.append(post)
        }
    }
}

或者干脆使用filter 之类的高阶方法,灵感来自@Jay 的评论。

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    filteredPosts = posts.filter { $0.name?.lowercased().contains(searchText.lowercased()) == true }
}

【讨论】:

  • @maya 发布的答案没有任何问题,除了应避免扩展循环。这有点短let filteredResults = posts.filter { $0.name.lowercased() == "string you're searching for".lowercased() }
  • @Jay 我什至不知道为什么我在答案中添加了额外的循环。我对您的建议进行了一些修改,例如我们不需要声明新变量filteredResults 我们可以直接将结果分配给filteredPosts 还包含搜索和可选的name 属性:)。
  • @Jay 我已更改我的代码以包含此内容(请参阅编辑),但 filteredResults 中没有任何值:print(filteredPosts.count) 正在返回帖子计数 = 0
  • @maya 查看问题的 cmets,但如果您需要帮助,则需要进行更多故障排除。例如,posts 数组实际上是否包含任何数据?键入时是否实际调用了委托函数?您是否在键入时添加了断点并检查了变量?结果如何?请参阅 - 我们无法为您做这些事情,但基本的故障排除可能会导致原因,并将提供更准确的信息以包含在问题中,以便我们继续进行。现在 - 我们只是猜测。
猜你喜欢
  • 2018-04-16
  • 2021-03-02
  • 1970-01-01
  • 2019-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-01
  • 1970-01-01
相关资源
最近更新 更多