【问题标题】:How to use reload item at instead of reloading all the data with firestore如何使用重新加载项目而不是使用firestore重新加载所有数据
【发布时间】:2021-04-21 06:04:07
【问题描述】:

我有一个使用 Firestore 的聊天应用程序,当一个新的 document or -> (message) 添加到 Firestore 时,我的 collectionView 重新加载所有数据,应用程序冻结一秒钟,直到所有数据重新加载,我不太了解collectionViews 但我认为如果没有错,这是因为 collectionView 试图计算每个单元格的大小,这是调试器消息

The relevant UICollectionViewFlowLayout instance is <UICollectionViewFlowLayout: 0x7fbd974b3c40>, and it is attached to <UICollectionView: 0x7fbd97930600; frame = (0 61; 414 663); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x600002c5df20>; layer = <CALayer: 0x6000023f9640>; contentOffset: {-5, -5}; contentSize: {404, 8}; adjustedContentInset: {5, 5, 5, 5}; layout: <UICollectionViewFlowLayout: 0x7fbd974b3c40>; dataSource: <DELEVARE___ديليفري.DriverChat: 0x7fbd97843600>>.
2021-01-16 13:54:43.232052+0200 DELEVARE - ديليفري[51104:999159] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.

symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.

这个调试器消息被调用repeated,每个单元格都加载到collectionView,这是我的collectionView How to solve UICollectionViewFlowLayoutBreakForInvalidSizes

我不知道如何只将新的附加项插入到 collectionView 中的数组中,我希望它能够像普通聊天应用一样做出反应。

我试过了

func getMessages(){
        guard let uid = Auth.auth().currentUser?.uid else {return}
        
        let firestore = Firestore.firestore()
        let doc = firestore.collection("طلبات قيد العمل").whereField("driverUid", isEqualTo: uid)
        doc.getDocuments { (query, err) in
            if err != nil {
                print(err?.localizedDescription ?? "")
            }
            for document in query!.documents{

                let chatDoc = document.reference.collection("المحادثات")

                chatDoc.addSnapshotListener { (querysnap, err) in
                    if err != nil {
                        print(err?.localizedDescription ?? "")
                    }
                    self.messages = []
                    for snap in querysnap!.documents{
                    
                    let data = snap.data()
                    guard let message = data["message"] as? String else {return}
                    guard let senderid = data["senderID"] as? String else {return}
                    guard let timestamp = data["date"] as? Timestamp else {return}
                    let date = Date(timeIntervalSince1970: TimeInterval(timestamp.seconds))
                    if senderid == Auth.auth().currentUser?.uid{
                        let drivermessages = driverMessages(image: UIImage(), text: message, date: date, isSender: true, driverid: senderid)

                        // this line of code is doing the same as collectionView.reloadData()

                        self.collectionView?.performBatchUpdates({
                            let indexPath = IndexPath(row: self.comments.count, section: 0)
                            self.messages.append(drivermessages)
                            self.collectionView?.insertItems(at: [indexPath])
                        }, completion: nil)
                        
                    }else {
                        
                        guard let message2 = data["message"] as? String else {return}
                        guard let senderid2 = data["senderID"] as? String else {return}
                        guard let timestamp2 = data["date"] as? Timestamp else {return}
                        guard let img = self.profileImg else {return}
                        let date2 = Date(timeIntervalSince1970: TimeInterval(timestamp2.seconds))
                        
                        let usermessages = driverMessages(image: img, text: message2, date: date2, isSender: false, driverid: senderid2)
                        self.messages.append(usermessages)
                        
                        self.collectionView?.performBatchUpdates({
                            let indexPath = IndexPath(row: self.comments.count, section: 0)
                            self.messages.append(usermessages)
                            self.collectionView?.insertItems(at: [indexPath])
                        }, completion: nil)
                        
                        }
                            
                     }
                 }
                
             }
         }
      }

这是我的代码

func getMessages(){
        guard let uid = Auth.auth().currentUser?.uid else {return}

        
        let firestore = Firestore.firestore()
        let doc = firestore.collection("طلبات قيد العمل").whereField("driverUid", isEqualTo: uid)
        doc.getDocuments { (query, err) in
            if err != nil {
                print(err?.localizedDescription ?? "")
            }
            for document in query!.documents{
                let chatDoc = document.reference.collection("المحادثات")

                chatDoc.addSnapshotListener { (querysnap, err) in
                    if err != nil {
                        print(err?.localizedDescription ?? "")
                    }
                    self.messages = []
                    for snap in querysnap!.documents{
                    
                    let data = snap.data()
                    guard let message = data["message"] as? String else {return}
                    guard let senderid = data["senderID"] as? String else {return}
                    guard let timestamp = data["date"] as? Timestamp else {return}
                    let date = Date(timeIntervalSince1970: TimeInterval(timestamp.seconds))
                    if senderid == Auth.auth().currentUser?.uid{
                        let drivermessages = driverMessages(image: UIImage(), text: message, date: date, isSender: true, driverid: senderid)
                        self.messages.append(drivermessages)
                        
                    }else {
                        
                        guard let message2 = data["message"] as? String else {return}
                        guard let senderid2 = data["senderID"] as? String else {return}
                        guard let timestamp2 = data["date"] as? Timestamp else {return}
                        guard let img = self.profileImg else {return}
                        let date2 = Date(timeIntervalSince1970: TimeInterval(timestamp2.seconds))
                        
                        let usermessages = driverMessages(image: img, text: message2, date: date2, isSender: false, driverid: senderid2)
                        self.messages.append(usermessages)
                        
                        }
                        DispatchQueue.main.async {
                            self.collectionView.reloadData()
                            let item = self.messages.count - 1
                            let insertionIndexPath = IndexPath(item: item, section: 0)
                            self.collectionView.scrollToItem(at: insertionIndexPath, at: .bottom, animated: true)
                        }
                            
                     }
                 }
                
             }
         }
      }

【问题讨论】:

    标签: ios swift google-cloud-firestore uicollectionview


    【解决方案1】:

    我对自己编码非常陌生。 但是,在我看来,可以帮助您的事情是让.onSnapshot 侦听器寻找change 类型为added

    https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/DocumentChange.Type

    我发现这篇文章对我正在开发的 CRUD 应用程序很有帮助:

    https://bezkoder.com/react-hooks-firestore/

    其中一部分展示了如何监听各种类型的变化。 我能够在我的应用程序中实现它以仅返回添加的文档而不是整个集合,然后将其附加到我的数组中。

       tutorialsRef.onSnapshot(function(snapshot) {
      snapshot.docChanges().forEach(function(change) {
        if (change.type === "added") {
          console.log("New tutorial: ", change.doc.data());
        }
        if (change.type === "modified") {
          console.log("Modified tutorial: ", change.doc.data());
        }
        if (change.type === "removed") {
          console.log("Removed tutorial: ", change.doc.data());
        }
      });
    });
    

    【讨论】:

    • 这意味着如果我在 viewDidload 上调用此方法,这意味着在发生新的更改之前它将无法工作.added, .delete, .modified ??而且它不会加载任何数据??
    • 老实说,我不明白你在做什么。但是对于我的应用程序,我可以让onSnapshot 使用.docChanges() 监听更改。我想如果我理解正确,这将返回一个对象,其中包括更改类型 - change.type - 更改的文档的 ID - change.doc.id - 以及文档的完整内容 - change.doc.data()。然后我检查了这个 doc.id 是否已经在我的状态中,如果没有,我将 doc 添加到我的状态对象数组中。这可能会对您有所帮助,因为 .onSnapshot 只会获取对 Firestore 的更改。 ...我认为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    相关资源
    最近更新 更多