如何在快速点击 Firestore 中的 uitablecellviewcell 时获取文档 ID

Posted

技术标签:

【中文标题】如何在快速点击 Firestore 中的 uitablecellviewcell 时获取文档 ID【英文标题】:how to get document id on tapping the uitablecellviewcell in Firestore in swift 【发布时间】:2019-08-30 08:02:38 【问题描述】:

如何在点击 UItableViewCell 时获取文档 ID?

我知道下面的代码确实给了我行索引,但是对于提要帖子,我想每次都获取特定帖子的文档 ID

我曾尝试通过模型文件中的密钥设置来检索文档 ID,但无济于事

  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        print("row selected: \(indexPath.row)")
        performSegue(withIdentifier: "toDetailView", sender: indexPath)
    

帖子模型

import Foundation
import Firebase
import FirebaseFirestore


protocol DocumentSerializable  
    init?(dictionary:[String:Any])



struct Post 

     var _username: String!
     var _postTitle: String!
     var _postcategory:  String!
     var _postContent:  String!




    var dictionary:[String:Any] 
        return [
            "username": _username,
            //"profile_pic":profile_pic,
            "postTitle":_postTitle,
            "postcategory":_postcategory,
            "postContent":_postContent
                   ]
    



extension Post : DocumentSerializable 

    init?(dictionary: [String : Any]) 
               guard let username = dictionary["username"] as? String,
           // let profile_pic = dictionary["profile_pic"] as? String,
            let postTitle = dictionary["postTitle"] as? String,
            let postcategory = dictionary["postcategory"] as? String,
            let postContent = dictionary["postContent"] as? String   else  return nil 


        self.init( _username: username ,_postTitle: postTitle, _postcategory: postcategory, _postContent: postContent)

    

将整个集合检索到的代码。表格视图

import Foundation
import UIKit
import Firebase


class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource 

    var tableView:UITableView!

    var posts = [Post]()
    var db: Firestore!

    var postKey:String = ""
    private var documents: [DocumentSnapshot] = []
    //public var posts: [Post] = []
    private var listener : ListenerRegistration!




    override func viewDidLoad() 
        super.viewDidLoad()

        db = Firestore.firestore()

        self.navigationController?.navigationBar.isTranslucent = false
        tableView = UITableView(frame: view.bounds, style: .plain)

        let cellNib = UINib(nibName: "PostTableViewCell", bundle: nil)
        tableView.register(cellNib, forCellReuseIdentifier: "postCell")
        tableView.backgroundColor = UIColor(white: 0.90,alpha:1.0)
        view.addSubview(tableView)

        var layoutGuide:UILayoutGuide!

        if #available(ios 11.0, *) 
            layoutGuide = view.safeAreaLayoutGuide
         else 
            // Fallback on earlier versions
            layoutGuide = view.layoutMarginsGuide
        

        tableView.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).isActive = true
        tableView.topAnchor.constraint(equalTo: layoutGuide.topAnchor).isActive = true
        tableView.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor).isActive = true

        tableView.delegate = self
        tableView.dataSource = self
        tableView.reloadData()
        retrieveAllPosts()
        //checkForUpdates()

    


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


   /* override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) 
        performSegueWithIdentifier("toDetailPage", sender: indexPath)
    

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
        let indexPath = self.tableView.indexPathForSelectedRow
        let person = personList[indexPath!.row]

        if segue.identifier == "toDetailPage"
            let DetailBookViewController = (segue.destinationViewController as! DetailPage)
            DetailBookViewController.user_name = user_name
            DetailBookViewController.user_age = user_age
            DetailBookViewController.user_urlPicture = user_urlPicture

        */
    @IBAction func handleLogout(_ sender:Any) 
        try! Auth.auth().signOut()
        self.dismiss(animated: false, completion: nil)
    

    /*func checkForUpdates() 
        db.collection("posts").whereField("timeStamp", isGreaterThan: Date())
            .addSnapshotListener 
                querySnapshot, error in

                guard let snapshot = querySnapshot else return

                snapshot.documentChanges.forEach 
                    diff in

                    if diff.type == .added 
                        self.posts.append(Post(dictionary: diff.document.data())!)
                        DispatchQueue.main.async 
                            self.tableView.reloadData()
                        
                    
                

        
    */

    func retrieveAllPosts()
        let postsRef = Firestore.firestore().collection("posts").limit(to: 50)

        postsRef.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()
                        self.postKey = document.documentID
                        let username = data["username"] as? String ?? ""
                        let postTitle = data["postTitle"] as? String ?? ""
                        let postcategory = data["postcategory"] as? String ?? ""
                        let postContent = data["postContent"] as? String ?? ""

                        let newSourse = Post(_postKey:self.postKey, _username: username, _postTitle: postTitle, _postcategory: postcategory, _postContent: postContent)
                        self.posts.append(newSourse)
                        print(self.postKey)
                    
                    self.tableView.reloadData()
                
            
        
    

       /* postsRef.getDocuments()  (querySnapshot, err) in
            if let err = err 
                print("Error getting documents: \(err)")
             else 
                for document in querySnapshot!.documents 
                    print("\(document.documentID) => \(document.data())")


                    self.posts = querySnapshot!.documents.flatMap(Post(dictionary: $0.data()))
                    DispatchQueue.main.async 
                        self.tableView.reloadData()

        

            
        */


    func numberOfSections(in tableView: UITableView) -> Int 
        return 1
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return posts.count
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
        cell.set(post: posts[indexPath.row])
        return cell
    

     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        print("row selected: \(indexPath.row)")

        //performSegue(withIdentifier: "toDetailView", sender: indexPath)
    

【问题讨论】:

我假设数据模型只包含 Firestore 返回的对象?只需将文档的 documentId 添加到您的数据模型类中。您需要添加更多关于如何加载数据的代码。 我已经更新了我的模型类,你能指导我如何在上面的类中添加documentId @inexcitus 只需将string 类型的新属性添加到您的Post 结构。然后在使用 Firestore 加载文档时,使用 DocumentReference 中的 documentId 并将其存储在您的 Post`` 实例中。 我请求您按照您所说的更新上面的代码,因为当它出于相同目的而初始化时,它会显示错误,我尝试了 *** 上可用的各种示例,但它总是显示一个或另一个错误 @inexcitus 请帮忙 【参考方案1】:

将新的 documentId 属性添加到您的 Post 结构:

struct Post 
    var _username: String!
    var _postTitle: String!
    var _postcategory:  String!
    var _postContent:  String!
    var _documentId: String! // This is new.

    var dictionary:[String : Any] 
        return [
            "documentId" : _documentId, // This is new.
            "username": _username,
            //"profile_pic":profile_pic,
            "postTitle":_postTitle,
            "postcategory":_postcategory,
            "postContent":_postContent
        ]
    


extension Post : DocumentSerializable

    init?(dictionary: [String : Any])
    
               guard let username = dictionary["username"] as? String,
           // let profile_pic = dictionary["profile_pic"] as? String,
            let postTitle = dictionary["postTitle"] as? String,
            let postcategory = dictionary["postcategory"] as? String,
            let documentId = dictionary["documentId"] as? String // This is new.
            let postContent = dictionary["postContent"] as? String   else  return nil 

            self.init( _username: username ,_postTitle: postTitle, _postcategory: postcategory, _postContent: postContent, _documentId: documentId)
    

更改您的retrieveAllPosts 函数并设置 Post 实例的 documentId,不要为此使用全局变量:

if let snapshot = snapshot

    for document in snapshot.documents
    
        let data = document.data()
        let username = data["username"] as? String ?? ""
        let postTitle = data["postTitle"] as? String ?? ""
        let postcategory = data["postcategory"] as? String ?? ""
        let postContent = data["postContent"] as? String ?? ""

        let newSourse = Post(_postKey:self.postKey, _username: username, _postTitle: postTitle, _postcategory: postcategory, _postContent: postContent, _documentId: document.documentId)
        self.posts.append(newSourse)
    

现在您可以在 didSelectRowAt 中访问所选 Post 的 documentId:

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

    let post = self.posts[indexPath.row]
    Swift.print(post.documentId)

    // print("row selected: \(indexPath.row)")
    // performSegue(withIdentifier: "toDetailView", sender: indexPath)

希望这将引导您走向正确的方向。

【讨论】:

非常感谢,好几天没用了,现在可以用了.....非常感谢

以上是关于如何在快速点击 Firestore 中的 uitablecellviewcell 时获取文档 ID的主要内容,如果未能解决你的问题,请参考以下文章

如何快速解码来自 Firebase Firestore 的时间戳

如何在 Swift 中从 Cloud FireStore Firebase 访问特定字段

在表格视图中点击按钮 - 错误的单元格

Vuejs 和 Firestore - 如何在 Firestore 中的数据更改时进行更新

无法让 Firestore 快速入门在 Python 中工作

如何在 firestore 中的现有数组中添加或删除项目?