Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.1k views
in Technique[技术] by (71.8m points)

ios - How to use reload item at instead of reloading all the data with firestore

I have a chat app use Firestore, when a new document or -> (message), added to the Firestore my collectionView reload all the data over again and the app freezes for a second until all the data reload, I don't know much about collectionViews but I think if am not wrong this happens because of the collectionView trying to calculate the size for each cell this is the debugger message

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.

this debugger message gets called repeated with every cell loaded to collectionView, Here is my collectionView How to solve UICollectionViewFlowLayoutBreakForInvalidSizes

I don't know how to insert only the new appended item to the array in collectionView, I want this just to react like a normal chat app.

I have tried this

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)
                        
                        }
                            
                     }
                 }
                
             }
         }
      }

this is my code

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)
                        }
                            
                     }
                 }
                
             }
         }
      }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I am very new to coding myself. However it seems to me something that could help you would be to have an .onSnapshot listener looking for change of type added.

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

I found this article very helpful for the the CRUD application I am working on:

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

Part of it shows how to listen for changes of various types. I was able to implement that into my app to return only the added document rather than the entire collection, and then append that to my array.

   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());
    }
  });
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...