问题描述
我正在使用GCD通知主线程(该函数内部有2个异步调用)
I'm using GCD to notify main thread (have 2 async calls inside the function)
我的代码:
func getWavesByMostRecent(closure: @escaping ([Wave]?) -> Void) {
var waves = [Wave]()
let dispatchGroup = DispatchGroup()
self.query = DatabaseManager.waveRef.queryOrdered(byChild: Constants.reverseTimeStampKey)
self.handle = self.query?.observe(.value, with: { (snapshot) in
for value in snapshot.children {
guard let wave = Wave(snapshot: value as! DataSnapshot) else { return }
self.geoFire = GeoFire(firebaseRef: DatabaseManager.waveRef)
let currentLocation = LocationManager.shared.getCurrentLocation()
dispatchGroup.enter()
self.geoFire?.getLocationForKey(wave.waveID, withCallback: { (location, error) in
guard let location = location else { return }
if error == nil {
if location.distance(from: currentLocation) < Constants.distance {
print("Wave", wave.waveID, "is in range")
waves.append(wave)
} else {
print("Wave", wave.waveID, "is out of range")
}
} else {
print(error?.localizedDescription ?? "")
}
dispatchGroup.leave()
})
}
dispatchGroup.notify(queue: .main) {
print("THERE ARE SO MANY WAVES:", waves.count)
closure(waves)
}
})
}
但是.notify闭包不起作用,我不能称呼我的主"闭包权.我究竟做错了什么?任何建议将不胜感激.
But .notify closure just doesn't work and I cannot call my "main" closure right. What am I doing wrong? Any advice would be appreciated.
推荐答案
尝试此更改:
self.geoFire?.getLocationForKey(wave.waveID, withCallback: { (location, error) in
defer { dispatchGroup.leave() }
guard let location = location else { return }
if error == nil {
if location.distance(from: currentLocation) < Constants.distance {
print("Wave", wave.waveID, "is in range")
waves.append(wave)
} else {
print("Wave", wave.waveID, "is out of range")
}
} else {
print(error?.localizedDescription ?? "")
}
})
如马特(Matt)的评论所述,defer
是一个总是在离开时做点什么的好工具.
As noted in matt's comment defer
is a good tool to do something always when leaving.
这是另一个问题,但是同时从多个线程更新数组会导致一些问题.这种情况很少发生,因此可能是一个难以修复的错误.
This is another issue, but updating an Array from multiple thread simultaneously would cause some problems. It rarely happens, so it can be a hard-to-fix bug.
我不确定GeoFire
是否在主线程中调用其回调,但是,如果没有,则最好将所有回调代码包含在DispatchQueue.main.async {...}
中.
I'm not sure if GeoFire
calls its callback in the main thread or not, but if not, you should better enclose all the callback code in DispatchQueue.main.async {...}
.
这篇关于如何在Swift(GCD)中通知队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!