我有一个bool" hasHaveProfile"我在while循环中更改为TRUE然后我退出循环...但是布尔值仍然没有变化。有什么想法吗?
if AccessToken.current != nil {
fetchUserData()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.5) {
let dref = FIRDatabase.database().reference().child("CheckUsers")
dref.observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in
var alreadyHaveProfile = false
let enumerator = snapshot.children
loop: while let user = enumerator.nextObject() as? FIRDataSnapshot {
if user.key == userID {
alreadyHaveProfile = true
break loop
}
}
}, withCancel: { (error: Error) in
print(error.localizedDescription)
})
print(alreadyHaveProfile)
**更新的答案:
if AccessToken.current != nil {
fetchUserData()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.5) {
let dref = FIRDatabase.database().reference().child("CheckUsers")
dref.observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in
var alreadyHaveProfile = false
let enumerator = snapshot.children
loop: while let user = enumerator.nextObject() as? FIRDataSnapshot {
if user.key == userID {
alreadyHaveProfile = true
self.finishSetUp()
break loop
}
}
}, withCancel: { (error: Error) in
print(error.localizedDescription)
})
}
finishSetUp() {
print(alreadyHaveProfile)
if !alreadyHaveProfile {
// finish set up, value of ALREADYHAVEPROFILE is recent and updated.
}
}
答案 0 :(得分:2)
Firebase方法observeSingleEvent(of:with:)
是异步的。也就是说,该方法在回调运行之前返回。
如果你像我在这里一样在你的代码中添加print语句,我想你会看到代码中出现第二个的print
语句是第一个出现在Xcode控制台中的语句。
if AccessToken.current != nil {
fetchUserData()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.5) {
let dref = FIRDatabase.database().reference().child("CheckUsers")
dref.observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in
var alreadyHaveProfile = false
let enumerator = snapshot.children
loop: while let user = enumerator.nextObject() as? FIRDataSnapshot {
if user.key == userID {
alreadyHaveProfile = true
print("1: \(alreadyHaveProfile)")
break loop
}
}
}, withCancel: { (error: Error) in
print(error.localizedDescription)
})
print("2: \(alreadyHaveProfile)")
答案 1 :(得分:2)
我怀疑变量alreadyHaveProfile
的状态尚未被循环内运行的逻辑设置。没有在我面前设置完整的场景设置使得很难诊断。
要考虑的几件事情;首先看起来FireBase正在执行一些数据库查询来设置变量的状态。要调试此尝试并设置一种方法来观察while循环运行的每次迭代,这样您就会知道在将print语句输出到控制台之前是否设置了变量alreadyHaveProfile
的状态。
这可能有助于确定您是否处于竞争状态。
let dref = FIRDatabase.database().reference().child("CheckUsers")
dref.observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in
var alreadyHaveProfile = false
var index = 0
if let userObjects = snapshot.children.allObjects {
for user in userObjects {
if user.key == userID {
alreadHaveProfile = true
}
index += 1
print("Value: \(alreadHaveProfile) at index: \(index) in count: \(userObjects.count)")
if index == userObjects.count {
print("Loop has completed: with value of: \(alreadHaveProfile)")
}
}
}
}, withCancel: { (error: Error) in
print(error.localizedDescription)
})
print("Setting initial value: \(alreadyHaveProfile)")
要考虑的第二件事是user.key和userID根本不匹配,并且正确设置了alreadyHaveProfile
值。要对此进行调试,请在循环内设置一些断点,以便在循环的每次迭代中查看user.key
和userID
。
答案 2 :(得分:0)
在异步块内部访问 alreadyHaveProfile 变量。
下面是代码:
if AccessToken.current != nil {
fetchUserData()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.5) {
let dref = FIRDatabase.database().reference().child("CheckUsers")
dref.observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in
var alreadyHaveProfile = false
let enumerator = snapshot.children
loop: while let user = enumerator.nextObject() as? FIRDataSnapshot {
if user.key == userID {
alreadyHaveProfile = true
print(alreadyHaveProfile)
break loop
}
}
}, withCancel: { (error: Error) in
print(error.localizedDescription)
})