【问题标题】:How to get specific information from Firestore when specific row is tapped点击特定行时如何从 Firestore 获取特定信息
【发布时间】:2019-12-10 11:38:56
【问题描述】:

这里的目标是在 Xcode 中的 Table View 中点击特定行时从 Firebase Firestore 获取特定信息。我已经找到了一种将数据存储到 Table View 中的方法: p>

func loadData() {
        FirebaseFirestore.root.collection("users").getDocuments { (snapshot, error) in
            if let error = error {
                print(error.localizedDescription)
            } else {
                if let snapshot = snapshot {

                    for document in snapshot.documents {

                        let data = document.data()
                        let name = data["name"] as? String ?? ""
                        let email = data["email"] as? String ?? ""
                        let phone = data["phone"] as? String ?? ""

                        let newPerson = Person(name: name, email: email, phone: phone)
                        self.people.append(newPerson)
                        print (self.people)

                        let newIndexPath = IndexPath(row: self.people.count - 1, section: 0)

                        self.table.beginUpdates()
                        self.table.insertRows(at: [newIndexPath], with: .automatic)
                        self.table.endUpdates()
                    }
                }
            }
        }
    }

运行时会显示:

例如,当我点击第 1 行时,我想进入另一个视图,该视图显示每个特定行的姓名、电子邮件、电话。这可能吗?如果是这样,我该怎么做?

------------------

到目前为止,我想为每一行添加另一个变量,但不显示在该行上。由于在 Firebase 中,文档 ID 是电子邮件,我可以将 var email 设置为每一行,并使用 getDocument() 通过电子邮件检索文档,即文档 ID。

我所做的只是使用变量 email 来尝试在 didSelectRowAt 函数上使用 getDocument。

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        let tappedUser = FirebaseFirestore.root.collection("users").document(email)

        performSegue(withIdentifier: "toPersonDesc", sender: nil)
    }

但这不起作用。我认为我不能使用 email 变量,因为它会为 Person.email 提供错误,而只是 email

任何帮助将不胜感激。

-------------------

如果有人需要,整个代码块(更新到我尝试过的):

import UIKit
import FirebaseFirestore

struct Person {
    let name, phone, email: String
}

class Cell: UITableViewCell {
    @IBOutlet weak var phone: UILabel!
    @IBOutlet weak var name: UILabel!
    @IBOutlet weak var email: UILabel!
}

class PeopleViewController: UITableViewController {

    @IBOutlet var table: UITableView!

    var people = [Person]()
    private var document: [DocumentSnapshot] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        table.tableFooterView = UIView(frame: CGRect.zero)
        self.table.delegate = self
        self.table.dataSource = self

        loadData()

    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return self.people.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let person = people[indexPath.row]
        let cell = self.table.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! Cell

        cell.name.text = person.name
        cell.phone.text = person.phone
        cell.email.text = person.email

        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        let tappedUser = FirebaseFirestore.root.collection("users").document(Person.email)//Error here

        performSegue(withIdentifier: "toPersonDesc", sender: nil)
    }

    func loadData() {
        FirebaseFirestore.root.collection("users").getDocuments { (snapshot, error) in
            if let error = error {
                print(error.localizedDescription)
            } else {
                if let snapshot = snapshot {

                    for document in snapshot.documents {

                        let data = document.data()
                        let name = data["name"] as? String ?? ""
                        let phone = data["phone"] as? String ?? ""
                        let email = data["email"] as? String ?? ""

                        let newPerson = Person(name: name, phone: phone, email: email)
                        self.people.append(newPerson)
                        print (self.people)

                        let newIndexPath = IndexPath(row: self.people.count - 1, section: 0)

                        self.table.beginUpdates()
                        self.table.insertRows(at: [newIndexPath], with: .automatic)
                        self.table.endUpdates()
                    }
                }
            }
        }
    }

【问题讨论】:

  • 有什么问题?你试过什么?
  • @Daniel,哦,抱歉,我还没有用我尝试过的方法编辑问题,我现在就编辑它。
  • 看看下面的答案。
  • 当用户点击时将该行电子邮件发送到下一个屏幕。在下一个屏幕上使用电子邮件查询数据库并获取您需要的所有数据。
  • @JawadAhmed,我如何将“电子邮件”发送到下一个屏幕?一旦我明白了,我想我可以完成剩下的。

标签: swift firebase uitableview google-cloud-firestore


【解决方案1】:

嘿,幸运的是,这实际上并不难。您需要做的就是这样:

//Create a custom UIViewController class which has a property of type Person.
class CustomViewController : UIViewController {    
    var person: Person?
    // You'll need to set this up using a .xib file
    weak var customView:CustomView?     
}

class UsersViewController : UIViewController, UITableViewDelegate {    
    var person:[Person]?

    //This method will be executed every time the user clicks on the row. Make sure that your current class adopts the UITableViewDelegate protocol.
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        //Insert your functionality to get the correct person and set the person property in the new custom view controller.
        let viewController = CustomViewController()
        viewController.person = self.person?[indexPath.row]
        // Display the new custom view controller.
        self.navigationController?.pushViewController(viewController, animated: true)
    }
}

解释:

  1. 创建一个具有 Person 类型属性的自定义 UIViewController 类。
  2. 此方法 - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) - 将在用户每次点击行时执行。 确保您当前的类采用 UITableViewDelegate 协议。
  3. 在 didSelectRow 函数中,插入您的功能以获取正确的人员并在新的自定义视图控制器中设置人员属性。
  4. 显示新的自定义视图控制器。

您需要确保设置视图控制器的视图以显示人员对象中的数据。如果您需要知道如何操作,请查看此video

如果您想对此进行任何澄清,请告诉我!

编辑:

有多种方法可以做到这一点。 Firebase 具有监视文档的功能,如果文档服务器端发生更改,您可以在应用程序中应用这些更改。看看here

我可能会考虑使用类似的东西。

或者您可以在 didSelectRow 中获取数据,然后在检索到数据后显示新的视图控制器。

【讨论】:

  • 您好,感谢您的回答,但是我是使用情节提要还是使用 xib 文件?我有点困惑。另外,我希望看看当点击一行时如何提取数据。例如,当我点击第一行时,我会从 Firestore 中获取第一行的额外数据并将其输入到另一个视图中。你知道怎么做吗?
  • 在 prepareForSegue 方法中将 person 对象设置在 segue.destinationViewController 对象上。然后在 viewDidLoad 方法中,您可以运行代码以从 Firebase 获取额外数据。但是您需要 Firebase 提供哪些额外数据?一旦我得到这些信息,我可以提供更详细的解释
  • 我正在根据您的位置创建一个应用程序,所以我需要邮政编码。然后,当我点击一行时,它会显示姓名、电子邮件、电话和邮政编码。另外,作为一个附带问题,您知道如何将电子邮件变量转换为公共变量吗?
  • 一个简单的说明可能会解决这个问题,即您是否拥有第一个表格视图中的所有数据或只有邮政编码列表?无论如何,这个来自苹果的快速入门指南将帮助您解决您的问题(关于在视图控制器之间传递数据的部分)developer.apple.com/library/archive/referencelibrary/…
  • @existingperson 我刚刚更新了我的答案,也许它会有所帮助。此外,要使电子邮件变量公开,您需要将其声明移到闭包之外并移至类级别。也许这篇文章可以帮助你。 docs.swift.org/swift-book/LanguageGuide/AccessControl.html 或者您可能想在 Google 上搜索 Swift 中的变量。
猜你喜欢
  • 1970-01-01
  • 2014-12-16
  • 2022-01-28
  • 2015-04-10
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 2019-08-28
  • 1970-01-01
相关资源
最近更新 更多