2017-06-06 6 views
5

Firebaseリアルタイムデータベースを使用したiOS迅速アプリケーションがあります。これまでアプリを普通に使っていれば、何の問題も見つけられません。しかし、私はエッジケースを予期したい。Firebaseリアルタイムアレイ数の不一致

私はアップデートをプッシュする前に私のアプリをテストすることを試みています。私がやっていることの1つは、詳細ビューVCである次のVCへのtableViewを持つVCからすぐに行き来しています。私が数回それを行うと、最終的に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か何かにfirebaseメソッドを使用する必要がありますか? – RubberDucky4444

+0

十分なコードが表示されているかわかりません。 viewDid/WillAppearのようなものは、テーブルメソッドと、テーブルデータを含む配列のセッター/ゲッタープロパティと同様に役立ちます。通常、テーブルに重複データの問題がある場合は、テーブルのデータ配列がリロードされる前にクリアされていないためです。異なる2つのビュー間を行き来するとき、たとえば、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をたくさん持っています(私の視覚的な方法で、unwrapped vars imoで遊ぶのに役立ちます)。 – murphguy

+0

@murphguy yea私はもっと良くなるために必要なことがたくさんあります...ガードはその一つです – RubberDucky4444