2016-06-12 23 views
6

Kullanıcıların yeni iletilerden haberdar edilmeleri gereken bir sohbet uygulamasında çalışıyorum. Bu bildirim mesajı ayrıca okunmamış mesajların sayısını da içermelidir. Hem gönderici hem de alıcı bu bilgiyi güncelleyebildiğinden, runTransaction tercih edilir. Ne yazık ki bazen işe yaramıyor. Bu "sıkışmış" hissediyor ve bir süre sonra tekrar çalışmaya başlıyor. privateChats düğümü (aşağıya bakın) her zaman en son iletiyle güncellenir, ancak openChatMessages düğümünü değil.Firebase/iOS: runTransactions bazen işe yaramıyor

Bu, kısa bir süre içinde çok sayıda ileti gönderilirse, yani runTransactions aynı ref için çok sık gerçekleştiriliyorsa bu olabilir mi?

Benim veri yapısı:

privateChats 
    $userId 
     $chatId 
      $messageId 
       text 
       timestamp 
       senderId 
       senderEmail 
       senderName 

// this node contains information about open chats 
// like last message and counter for unread messages 
openChatMessages 
    $userId 
     $chatId 
      text 
      timestamp 
      senderId 
      senderEmail 
      senderName 
      counter 

Kodum:

class ChatViewController: JSQMessagesViewController { 

    var user: FIRUser! 
    var ref: FIRDatabaseReference! 
    var chatRef: FIRDatabaseReference! 
    var senderOpenChatRef: FIRDatabaseReference! 
    var receiverOpenChatRef: FIRDatabaseReference! 

    // the following variables will be set before ChatViewController appears 

    var chatId: String? 
    var receivId: String? 
    var receiverEmail: String? 
    var receiverName: String? 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.user = FIRAuth.auth()?.currentUser! 
     self.ref = FIRDatabase.database().reference() 
     self.chatRef = self.ref.child("privateChats").child(self.user.uid).child(self.chatId!) 
     self.senderOpenChatRef = self.ref.child("openChatMessages").child(self.user.uid).child(self.chatId!) 
     self.receiverOpenChatRef = self.ref.child("openChatMessages").child(self.receiverId!).child(self.chatId!) 
    } 

    func sendMessage(text: String) { 
     var messageObject = [String: AnyObject]() 
     messageObject["text"] = text 
     messageObject["timestamp"] = FIRServerValue.timestamp() 
     messageObject["senderEmail"] = self.user.email 
     messageObject["senderName"] = self.user.displayName 
     messageObject["senderId"] = self.user.uid 

     let messageId = self.ref.child("privateChats").child(self.user.uid).child(self.chatId!).childByAutoId().key 

     let childUpdates = [ 
      "/privateChats/\(self.user.uid)/\(self.chatId!)/\(messageId)": messageObject, 
      "/privateChats/\(self.receiverId!)/\(self.chatId!)/\(messageId)": messageObject 
     ] 

     self.ref.updateChildValues(childUpdates, withCompletionBlock: { (error, ref) -> Void in 
      if error != nil { 
       print("childUpdates error:\(error)") 
       return 
      } 

      JSQSystemSoundPlayer.jsq_playMessageSentSound() 
      self.finishSendingMessage() 
      self.updateOpenChats(text) 
     }) 
    } 


    func updateOpenChats(text: String) { 

     // update the receivers openChatObject with increasing the counter 
     self.receiverOpenChatRef.runTransactionBlock({ (currentData: FIRMutableData) -> FIRTransactionResult in 

      var openChatObject = [String: AnyObject]() 

      // update openChatObject with the latest information from currentData 
      if currentData.hasChildren() { 
       openChatObject = currentData.value as! [String: AnyObject] 
      } 

      openChatObject["text"] = text 
      openChatObject["timestamp"] = FIRServerValue.timestamp() 
      openChatObject["senderEmail"] = self.user.email 
      openChatObject["senderName"] = self.user.displayName 
      openChatObject["senderId"] = self.user.uid 

      var counter = openChatObject["counter"] as? Int 
      if counter == nil { 
       counter = 1 
      } else { 
       counter = counter! + 1 
      } 
      openChatObject["counter"] = counter 

      currentData.value = openChatObject 
      return FIRTransactionResult.successWithValue(currentData) 
      }) { (error, committed, snapshot) in 
       if let error = error { 
        print("updateOpenChats: \(error.localizedDescription)") 
       } 
     } 

     // update your (the sender's) openChatObject with setting the counter to zero 
     self.senderOpenChatRef.runTransactionBlock({ (currentData: FIRMutableData) -> FIRTransactionResult in 

      var openChatObject = [String: AnyObject]() 

      // update openChatObject with the latest information from currentData 
      if currentData.hasChildren() { 
       openChatObject = currentData.value as! [String: AnyObject] 
      } 

      openChatObject["text"] = text 
      openChatObject["timestamp"] = FIRServerValue.timestamp() 
      openChatObject["senderEmail"] = self.receiverEmail 
      openChatObject["senderName"] = self.receiverName 
      openChatObject["senderId"] = self.receiverId 
      openChatObject["counter"] = 0 

      currentData.value = openChatObject 
      return FIRTransactionResult.successWithValue(currentData) 
      }) { (error, committed, snapshot) in 
       if let error = error { 
        print(error.localizedDescription) 
       } 
     } 
    } 
} 

DÜZENLEME: böcek hala devam benim ilk cevabım benim beklentileri

aksine. Bağlantıyla ilgili bir şey var mı? Örneğin. İyi bir bağlantı olmadığında, bazen işlemi yürütmek daha uzun sürer? Ancak bazen yönlendiricinin hemen yanında oturduğumda da oluyor. Diğer düğümler, yazılı olanlara değil, yazılır. Bu durumlarda uygulamayı yeniden başlattıktan sonra tekrar çalışmaya başlar. Yani sanırım kaputun altında bir sorun var.

Bu sorunla ilgili çözümleri çok takdir ediyorum. Alıcının bazen yeni mesajlarla ilgili bildirim almadığı bir sohbet uygulamasıdır.

Ayrıca geçici çözümler ile de iyiyim: Bir sayacı artırmak istediğinizde işlemler gerçekten gerekli midir? setValue ile text, senderId veya timestamp gibi diğer verileri güncelleştirebiliriz, ancak her iki kullanıcı da aynı anda alt düğümlerin değerini ayarlamaya çalıştıklarında, bozuk veri yol açabilirdi, değil mi?

func sendMessage(text: String?, video: NSURL?, image: UIImage?) { 

    var messageObject = [String: AnyObject]() 
    messageObject["text"] = text 
    messageObject["timestamp"] = FIRServerValue.timestamp() 
    messageObject["senderEmail"] = self.user.email 
    messageObject["senderName"] = self.user.displayName 
    messageObject["senderId"] = self.user.uid 

    func completeSending() { 
     let messagesRef = self.ref.child("messages").child(self.chatId!).childByAutoId() 
     messagesRef.setValue(messageObject) 

     JSQSystemSoundPlayer.jsq_playMessageSentSound() 
     if let _ = image { 
      self.updateOpenChats(" Photo") 
     } else if let text = text { 
      self.updateOpenChats(text) 
     } 

     self.finishSendingMessageAnimated(true) 
    } 

    if let image = image { // if an image is being sent 
     let data: NSData = UIImageJPEGRepresentation(image, 0.37)! 
     let fileName = "image_\(NSDate().timeIntervalSince1970).jpg" 
     let chatImagesRef = storageRef.child("chatImages/\(self.chatId!)/\(fileName)") 
     let uploadTask = chatImagesRef.putData(data, metadata: nil) { metadata, error in 
      if (error != nil) { 
       print(error) 
       return 
      } 
     } 

     uploadTask.observeStatus(.Failure) { snapshot in 
      ProgressHUD.showError("Uploading image failed.") 
     } 

     uploadTask.observeStatus(.Success) { snapshot in 
      let imageUrl = snapshot.reference 
      messageObject["imageUrl"] = String(imageUrl) 
      completeSending() 
     } 
    } else { // if it's just a text message 
     completeSending() 
    } 

} 

func updateOpenChats(text: String) { 

     self.receiverChatRef.runTransactionBlock({ (currentData: FIRMutableData) -> FIRTransactionResult in 

      var openChatObject = [String: AnyObject]() 

      if currentData.hasChildren() { 
       openChatObject = currentData.value as! [String: AnyObject] 
      } 

      openChatObject["text"] = text 
      openChatObject["timestamp"] = FIRServerValue.timestamp() 
      openChatObject["senderEmail"] = self.user.email 
      openChatObject["senderName"] = self.user.displayName 
      openChatObject["senderId"] = self.user.uid 
      openChatObject["pushId"] = Database.pushId 

      var counter = openChatObject["counter"] as? Int 
      if counter == nil { 
       counter = 1 
      } else { 
       counter = counter! + 1 
      } 
      openChatObject["counter"] = counter 

      // Set value and report transaction success 
      currentData.value = openChatObject 
      return FIRTransactionResult.successWithValue(currentData) 
     }) { (error, committed, snapshot) in 
      if let error = error { 
       print("updateOpenChats: \(error.localizedDescription)") 
      } 
     } 

     self.senderChatRef.runTransactionBlock({ (currentData: FIRMutableData) -> FIRTransactionResult in 
      var openChatObject = [String: AnyObject]() 

      if currentData.hasChildren() { 
       openChatObject = currentData.value as! [String: AnyObject] 
      } 

      openChatObject["text"] = text 
      openChatObject["timestamp"] = FIRServerValue.timestamp() 
      openChatObject["senderEmail"] = self.receiver.email 
      openChatObject["senderName"] = self.receiver.name 
      openChatObject["senderId"] = self.receiver.uid 
      openChatObject["counter"] = 0 

      // Set value and report transaction success 
      currentData.value = openChatObject 
      return FIRTransactionResult.successWithValue(currentData) 
     }) { (error, committed, snapshot) in 
      if let error = error { 
       print(error.localizedDescription) 
      } 
    } 
} 
+0

Şu anda aynı sorunu yaşıyorum. Herhangi bir çözüm? –

+0

@ MJQZ1347 Bu sorunu yaşıyorum da bir çözüm buldunuz mu? –

cevap

4

Tamam, görünüşe göre Firebase SDK bir hata vardır:

İşte benim son kod. Güncelleme başarılı olsa bile updateChildValues'un geri çağrısı bazen yürütülmez. completionBlock'u kaldırdım ve şimdi kusursuz çalışıyor.

self.ref.updateChildValues(childUpdates) 
    JSQSystemSoundPlayer.jsq_playMessageSentSound() 
    self.finishSendingMessage() 
    self.updateOpenChats(text) 

DÜZENLEME: güncellenmiş soruya bakın, sorun oluşmaya devam eder.

+0

Hala 3.5.1'de meydana geliyor, çok sinir bozucu – Markus