2017-06-06 59 views
5

我有一个使用Firebase实时数据库的iOS快速应用程序。如果我通常到目前为止使用该应用程序,我找不到任何问题。但是,我想预测边缘情况。Firebase实时阵列计数不匹配

我试图在我推送更新之前测试我的应用程序,而且我正在做的一种方式是快速地从具有tableView的VC到来到VC,这是一个详细的VC。如果我做了几次,最终tableview会显示大量重复的数据。

我已经通过在我的模拟器上打开tableview并进入我的Firebase控制台并手动更改值并在设备上即时更改字符串来测试了我的应用程序。

所以我很困惑,为什么我的tableview会显示不正确的孩子数量,如果它不断检查值应该是什么。

// 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

我需要使用的numberOfItemsInSection或东西火力方法? – RubberDucky4444

+0

不确定我们看到了足够的代码。诸如viewDid/WillAppear之类的东西对于表格方法和包含表格数据的数组上的任何setter/getter属性都会有所帮助。通常,当表中存在重复数据的问题时,这是因为表的数据数组在重新加载之前未被清除。当您在两个不同视图之间来回切换时,例如,每当您切换回表视图时,都会调用viewWillAppear中的任何内容。 – C6Silver

回答

4

我得到的帮助和改变了我的代码厉害,所以现在它的工作原理

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

看起来不错,我建议在这里使用一些警戒声明。通常,当我有很多if-elses时,我会这样做(即时视觉,这有助于打开未打包的变量imo)。 – murphguy

+0

@murphguy yea我有很多事情需要改进......后卫是其中之一 – RubberDucky4444