Swift:向Firebase变量添加值时如何修复无限循环 [英] Swift: How to fix infinite loop when adding a value to a Firebase variable

查看:104
本文介绍了Swift:向Firebase变量添加值时如何修复无限循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在程序中有这样一段代码,应该允许用户点击一条消息,分数应该增加一个:

  super.collectionView(collectionView,didTapMessageBubbleAtIndexPath:indexPath)
let data = self.messages [indexPath.row]

print(They tapped:+(data.text) + - +(data.senderDisplayName))

let rootRef:FIRDatabaseReference = FIRDatabase.database()。reference()
let senderID = FIRAuth.auth()!currentUser !. ($)

rootRef.child(messages)。如果snap.exists(){
if messageDict = snap.value!as?[String:AnyObject]
{
for messagesDict as [String:AnyObject] {

让postID = each.0
如果让messageDict = each.1 as?[Str ing:AnyObject] {
如果senderID == messageDict [senderId] as!字符串{

//检查用户的senderID,以便只增加特定消息的分数
var userScore = messageDict [score] as! Int
userScore = userScore + 1
rootRef.child(messages)。child(postID).child(score)。setValue(userScore)

print(senderID )
print(messageDict [senderId])
print(userScore)
}
}
}
}
} $ b $然而,当上面的代码运行并且用户敲击消息时,得分变量确实在Firebase中增加,但是它永远不会停止运行。这导致分数无限增加,这不是我正在寻找的。我希望我的代码只是一次添加一个分数,但似乎并不奏效。任何人都可以帮助我找到我的无限循环,或建议一种方式,我可以更有效地添加到我的分数变量在Firebase中?



谢谢!



我也知道一个事实,即函数不会自己运行多次,因为print语句: print(they tapped:+(data.text)+ - +(data.senderDisplayName ))只打印一次,并返回正确的数据。

解决方案

伊万的答案将解决你目前的问题。但是从服务器加载所有消息来检测用户点击的消息听起来像是一个潜在的大带宽浪费。



如果您显示的是Firebase中的消息列表,用户,我建议跟踪每条消息的关键。有了这些信息,您将不会扫描所有消息,而是可以直接查找单击的消息,并通过事务提高分数:

 $ {code> rootRef.child(messages)。child(postID).child(score)。runTransactionBlock({(currentData:FIRMutableData) - > FIRTransactionResult in 
//设置值和报告事务成功
currentData.value = currentData.value + 1
返回FIRTransactionResult.successWithValue(currentData)
}){(error,committed,snapshot)in
if error = error {
print(error.localizedDescription)
}
}

交易还将解决您现在可能遇到的竞争状况:如果两个用户几乎同时点击相同的消息,则可能会覆盖另一个消息的分数增量。

I have this piece of code in my program that should allow a user to tap on a message and the score should increase by one:

super.collectionView(collectionView, didTapMessageBubbleAtIndexPath: indexPath)
        let data = self.messages[indexPath.row]

        print("They tapped: "  + (data.text) + "- " + (data.senderDisplayName))

        let rootRef : FIRDatabaseReference = FIRDatabase.database().reference()
        let senderID = FIRAuth.auth()!.currentUser!.uid

        rootRef.child("messages").observeEventType(.Value, withBlock: { (snap) in

            print(senderID)

            if snap.exists(){
                if let messagesDict = snap.value! as? [String : AnyObject]
                {
                    for each in messagesDict as [String : AnyObject]{

                        let postID = each.0
                        if let messageDict = each.1 as? [String:AnyObject]{
                            if senderID == messageDict["senderId"] as! String{

                                //Checking for the senderID of the user so that you only increment the score of that particular message post
                                var userScore = messageDict["score"] as! Int
                                userScore = userScore + 1
                                rootRef.child("messages").child(postID).child("score").setValue(userScore)

                                print(senderID)
                                print(messageDict["senderId"])
                                print(userScore)
                            }
                        }                   
                    }
                }
            }
        })

However, when the above code is run and a user taps on a message, the score variable does increase in Firebase however it never stops running. This causes the score to increase infinitely which is not what I am looking for. I wanted my code to just add one to the score a single time, but that doesn't seem to be working. Would anybody be able to help me find my infinite loop or suggest a way where I could more efficiently add to my score variable in Firebase?

Thanks!

P.s. I also know for a fact that the function doesn't run multiple times by itself because the print statement: print("They tapped: " + (data.text) + "- " + (data.senderDisplayName)) only prints once, and returns the correct data.

解决方案

Ivan's answer will solve the current problem you have. But loading all messages from the server to detect which one the user clicked sounds like a potentially big waste of bandwidth.

If you're showing a list of messages from Firebase to the user, I recommend keeping track of the key of each message. With that information, you won't have scan all messages, but can instead directly look up the message that was clicked and increase its score with a transaction:

rootRef.child("messages").child(postID).child("score").runTransactionBlock({ (currentData: FIRMutableData) -> FIRTransactionResult in
  // Set value and report transaction success
  currentData.value = currentData.value + 1
  return FIRTransactionResult.successWithValue(currentData)
}) { (error, committed, snapshot) in
  if let error = error {
    print(error.localizedDescription)
  }
}

A transaction will also solve the potential race condition you now have: if two users click the same message at almost the same time, one might be overwriting the score-increment of the other.

这篇关于Swift:向Firebase变量添加值时如何修复无限循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆