Swift 为什么我的计数器落后于实际值1?

Swift 为什么我的计数器落后于实际值1?,swift,firebase,google-cloud-firestore,Swift,Firebase,Google Cloud Firestore,我正在尝试实现swift中描述的分布式计数器。以下是我所拥有的: 导入UIKit 导入FirebaseFirestore 类ViewController:UIViewController{ 让db=Firestore.Firestore().collection(“数据库”).document(“计数器”) var returnCount=0 @IBVAR计数器标签:UILabel! @IBV出口弱var计数器按钮:UIButton! 重写func viewDidLoad(){ super.v

我正在尝试实现swift中描述的分布式计数器。以下是我所拥有的:


导入UIKit
导入FirebaseFirestore
类ViewController:UIViewController{
让db=Firestore.Firestore().collection(“数据库”).document(“计数器”)
var returnCount=0
@IBVAR计数器标签:UILabel!
@IBV出口弱var计数器按钮:UIButton!
重写func viewDidLoad(){
super.viewDidLoad()
createCounter(参考号:db,numShards:5)
}
//[启动计数器结构]
@iAction func已反压(\发送方:UIButton){
递增计数器(参考号:db,numShards:5)
counterLabel.text=String(getCount(ref:db))
}
//计数器/${ID}
结构计数器{
让numShards:Int
初始化(numShards:Int){
self.numShards=numShards
}
}
//计数器/${ID}/shard/${NUM}
结构碎片{
计数:Int
初始化(计数:Int){
self.count=计数
}
}
//[结束计数器结构]
//[开始创建\u计数器]
func createCounter(ref:DocumentReference,numShards:Int){
中的ref.setData([“numShards”:numShards]){(err)
因为我在0…numShards{
ref.collection(“shard”).document(String(i)).setData([“count”:0])
}
}
}
//[结束创建\u计数器]
//[启动增量计数器]
func incrementCounter(ref:DocumentReference,numShards:Int){
//随机选择计数器的碎片
设shardId=Int(arc4random_统一(UInt32(numShards)))
让shardRef=ref.collection(“shards”).document(字符串(shardId))
更新数据([
“计数”:字段值。增量(Int64(1))
])
}
//[结束增量计数器]
//[开始计数]
func getCount(ref:DocumentReference)->Int{
中的ref.collection(“shard”).getDocuments(){(querySnapshot,err)
var totalCount=0
如果错误!=零{
打印(错误??“错误”)
}否则{
用于querySnapshot!.documents中的文档{
让count=document.data()[“count”]as!Int
totalCount+=计数
}
}
self.returnCount=totalCount
打印(self.returnCount)
}
返回计数
}
//[结束计数]
}

但是,当我点击按钮时,它比应该的位置落后1。例如,当我运行应用程序并按下按钮时,它显示0而不是1。我想我需要某种等待功能,但不确定它应该放在哪里或如何实现。我尝试在调度队列中运行它,但没有成功。

我找到了解决问题的方法。我没有尝试在
countpressed
函数中设置标签,而是在
getCount
函数中设置标签,如下所示:

func getCount(ref:DocumentReference){
中的ref.collection(“shard”).getDocuments(){(querySnapshot,err)
var totalCount=0
如果错误!=零{
打印(错误??“错误”)
}否则{
用于querySnapshot!.documents中的文档{
让count=document.data()[“count”]as!Int
totalCount+=计数
}
}
self.counterLabel.text=字符串(totalCount)
}
}

然后在
viewDidLoad
counterPressed

中调用
getCount
。这个答案没有错,但随着数据库的增长,它可能会成为一个问题。简而言之,每次视图加载时,都会读取和迭代文档。100没有什么大不了的,但是当你有10000的时候,这就加起来了。但是,每当用户点击反压按钮时,这种循环就会再次发生(SLOWW)。一个选项是保留一个单独的集合/文档,该集合/文档存储计数,并在添加文档时递增计数。这样,您就可以删除迭代代码,只需阅读一个文档。此外,您还可以添加一个观察者,这样当计数器递增时,UI会自动更新。@Jay,如果我错了,请纠正我,但是
反压
不应该在O(n)时间内运行吗?这对我来说似乎并不太慢。也许我不理解。下面是我看到的代码——有两件事正在发生。给定100000个文档,当调用getCount时1)所有100000个文档都加载了.getDocuments,然后2)每个文档都被迭代(即100000次迭代),然后3)计数器标签更新。我相当确信,随着数据集的增长,响应性将变得越来越差。“也许还有更多?”杰伊不太清楚
getCount
始终只下拉五个文档。每个文档都有一个字段
count
,然后将其添加到总数中并返回(可能是固定时间?)。啊-不清楚您是否只对碎片进行了合计。知道了。然而,在你的问题中,你有一个放错地方的返回声明。在
getCount
函数中,您得到了
ref.collection(“shards”).getDocuments(){}return
,并且闭包后的return语句将在
getDocuments
闭包中的代码之前执行。这可能也会引起一个问题。