2017-06-06 6 views
5

Ich habe eine iOS Swift App, die Firebase Realtime-Datenbank verwendet. Wenn ich die App bisher normal nutze finde ich kein Problem. Ich möchte jedoch Randfälle vorhersehen.Firebase Echtzeit Array-Anzahl stimmt nicht überein

Ich versuche Stress meine App zu testen, bevor ich das Update schiebe, und eine Möglichkeit, die ich tue, geht schnell von einem VC mit einem TableView zum nächsten VC, der ein Detail VC ist. Wenn ich es mehrere Male tue, zeigt die Tabelle schließlich viele doppelte Daten an.

Ich habe meine App getestet, indem ich eine Tabellenansicht auf meinem Simulator geöffnet habe und in meine Firebase-Konsole wechselte und manuell einen Wert änderte und sofort auf dem Gerät die Zeichenfolge änderte.

So bin ich verwirrt, warum mein Tableview würde eine falsche Anzahl von Kindern zeigen, wenn es ständig überprüft, was der Wert sein sollte.

// MARK: Firebase Methods 

func checkIfDataExits() { 
    DispatchQueue.main.async { 
     self.cardArray.removeAll() 
     self.ref.observe(DataEventType.value, with: { (snapshot) in 
      if snapshot.hasChild("cards") { 
       self.pullAllUsersCards() 
      } else { 
       self.tableView.reloadData() 
      } 
     }) 
    } 
} 



func pullAllUsersCards() { 
    cardArray.removeAll() 
    let userRef = ref.child("users").child((user?.uid)!).child("cards") 
    userRef.observe(DataEventType.value, with: { (snapshot) in 
     for userscard in snapshot.children { 
      let cardID = (userscard as AnyObject).key as String 
      let cardRef = self.ref.child("cards").child(cardID) 
      cardRef.observe(DataEventType.value, with: { (cardSnapShot) in 
       let cardSnap = cardSnapShot as DataSnapshot 
       let cardDict = cardSnap.value as! [String: AnyObject] 
       let cardNickname = cardDict["nickname"] 
       let cardType = cardDict["type"] 
       let cardStatus = cardDict["cardStatus"] 
       self.cardNicknameToTransfer = cardNickname as! String 
       self.cardtypeToTransfer = cardType as! String 
       let aCard = CardClass() 
       aCard.cardID = cardID 
       aCard.nickname = cardNickname as! String 
       aCard.type = cardType as! String 
       aCard.cStatus = cardStatus as! Bool 
       self.cardArray.append(aCard) 
       DispatchQueue.main.async { 
        self.tableView.reloadData() 
       } 
      }) 
     } 
    }) 
} 
+0

Habe ich eine Feuerbasis Methode auf dem numberOfItemsInSection oder etwas verwenden? – RubberDucky4444

+0

Nicht sicher, ob wir genug Code sehen. Dinge wie viewDid/WillAppear wären ebenso hilfreich wie die Tabellenmethoden und alle Setter/Getter-Eigenschaften in dem Array, das die Tabellendaten enthält. Wenn Probleme mit doppelten Daten in einer Tabelle auftreten, liegt dies in der Regel daran, dass der Datenarray der Tabelle vor dem erneuten Laden nicht gelöscht wird. Wenn Sie zwischen zwei verschiedenen Ansichten hin- und hergehen, wird bei jedem Wechsel in die Tabellenansicht beispielsweise in viewWillAppear alles aufgerufen. – C6Silver

Antwort

4

Ich bekam Hilfe und drastisch verändern meinen Code, es so funktioniert jetzt

func checkIfDataExits() { 
    self.ref.observe(DataEventType.value, with: { (snapshot) in 
     if snapshot.hasChild("services") { 
      self.pullCardData() 
     } else { 
      DispatchQueue.main.async { 
       self.collectionView.reloadData() 
      } 
     } 
    }) 
} 


func pullCardData() { 
    let cardRef = self.ref.child("cards") 
    cardRef.observe(DataEventType.value, with: { (snapshot) in 
     for cards in snapshot.children { 
      let allCardIDs = (cards as AnyObject).key as String 
      if allCardIDs == self.cardID { 
       if let childId = self.cardID { 
        let thisCardLocation = cardRef.child(childId) 
        thisCardLocation.observe(DataEventType.value, with: { (snapshot) in 
         let thisCardDetails = snapshot as DataSnapshot 
         if let cardDict = thisCardDetails.value as? [String: AnyObject] { 
          self.selectedCard?.cardID = thisCardDetails.key 
          self.selectedCard?.nickname = cardDict["nickname"] as? String ?? "" 
          self.selectedCard?.type = cardDict["type"] as? String ?? "" 
          self.pullServicesForCard() 
         } 
        }) 
       } 
      } 
     } 
    }) 
} 

func pullServicesForCard() { 
    if let theId = self.cardID { 
     let thisCardServices = self.ref.child("cards").child(theId).child("services") 
     thisCardServices.observe(DataEventType.value, with: { (serviceSnap) in 
      if self.serviceArray.count != Int(serviceSnap.childrenCount) { 
       self.serviceArray.removeAll() 
       self.fetchAndAddAllServices(serviceSnap: serviceSnap, index: 0, completion: { (success) in 
        if success { 
         DispatchQueue.main.async { 
          self.collectionView.reloadData() 
         } 
        } 
       }) 
      } 
     }) 
    } 
} 

func fetchAndAddAllServices(serviceSnap: DataSnapshot, index: Int, completion: @escaping (_ success: Bool) -> Void) { 
    if serviceSnap.hasChildren() { 
     if index < serviceSnap.children.allObjects.count { 
      let serviceChild = serviceSnap.children.allObjects[index] 
      let serviceID = (serviceChild as AnyObject).key as String 

      let thisServiceLocationInServiceNode = self.ref.child("services").child(serviceID) 

      thisServiceLocationInServiceNode.observeSingleEvent(of: DataEventType.value, with: { (thisSnap) in 
       let serv = thisSnap as DataSnapshot 

       if let serviceDict = serv.value as? [String: AnyObject] { 

        let aService = ServiceClass(serviceDict: serviceDict) 
        self.serviceCurrent = serviceDict["serviceStatus"] as? Bool 
        self.serviceName = serviceDict["serviceName"] as? String ?? "" 
        self.serviceURL = serviceDict["serviceURL"] as? String ?? "" 
        self.serviceFixedBool = serviceDict["serviceFixed"] as? Bool 
        self.serviceFixedAmount = serviceDict["serviceAmount"] as? String ?? "" 
        self.attentionInt = serviceDict["attentionInt"] as? Int 

        self.totalArr.append((serviceDict["serviceAmount"] as? String)!) 
        //      self.doubleArray = self.totalArr.flatMap{ Double($0) } 
        //      let arraySum = self.doubleArray.reduce(0, +) 
        //      self.title = self.selectedCard?.nickname ?? "" 

        //      if let titleName = self.selectedCard?.nickname { 
        //       self.title = "\(titleName): \(arraySum)" 
        //      } 

        aService.serviceID = serviceID 
        if serviceDict["serviceStatus"] as? Bool == true { 
         self.selectedCard?.cStatus = true 
        } else { 
         self.selectedCard?.cStatus = false 
        } 



        if !self.serviceArray.contains(where: { (service) -> Bool in 
         return service.serviceID == aService.serviceID 
        }) { 
         self.serviceArray.append(aService) 

         self.serviceArray.sort {$1.serviceAttention < $0.serviceAttention} 

        } 
       } 
       self.fetchAndAddAllServices(serviceSnap: serviceSnap, index: index + 1, completion: completion) 
      }) 

     } 
     else { 
      completion(true) 
     } 
    } 
    else { 
     completion(false) 
    } 

} 
+0

Sieht gut aus, ich würde hier einige Guard-Statements empfehlen. Normalerweise mache ich etwas, wenn ich viele If-Elen habe (im visuellen Sinne, hilft das Spielen mit unverpackten Vars imo). – murphguy

+0

@murphguy ja ich habe viele Dinge, die ich besser machen muss ... Wache ist einer von ihnen – RubberDucky4444