【发布时间】:2019-09-17 10:17:58
【问题描述】:
我运行下面的代码并使用打印语句数据库说孩子是null
但在数据库中肯定有一些东西:
我唯一能想到的就是让用户删除一条消息(通过删除-LoyeLv... 键),但如果他们想将其添加回来,他们可以。我保留了已删除密钥的副本,然后将其发送回数据库,以便消息仍然同步。唯一的问题是即使我不这样做(如在我的示例中)并且我删除了消息,回来并使用全新的密钥创建一个全新的消息,它仍然显示为空?
即使那里有孩子,这怎么可能?顺便说一句,这是我第一次遇到这种情况。
Database.database().reference()
.child("favorite")
.child(uid) // TKAETTLWAuREMZXCvrVeZd8yIPw2
.queryOrderedByKey()
.queryLimited(toLast: 10)
.observeSingleEvent(of: .value, with: { [weak self](snapshot) in
print(snapshot.key) // prints TKAETTLWAuREMZXCvrVeZd8yIPw2
print(snapshot.value) // prints null
if snapshot.hasChildren() {
print("yay")
} else {
print("nay") // prints nay
}
// doesn't go past here
guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return }
更新我刚刚在下面尝试过,它工作正常,但上面仍然不起作用:
Database.database().reference()
.child("favorite")
.child(uid) // prints TKAETTLWAuREMZXCvrVeZd8yIPw2
.observeSingleEvent(of: .value, with: { [weak self](snapshot) in
print(snapshot.key) // prints TKAETTLWAuREMZXCvrVeZd8yIPw2
print(snapshot.value) // prints the json data
if snapshot.hasChildren() {
print("yay") // prints nay
} else {
print("nay")
}
我想删除该引用处的密钥而不是添加相同的密钥而不是再次删除它而不是添加一个全新的密钥会以某种方式抛出数据库?
再次更新我没有使用 .queryOrderedByKey() 而是将其更改为使用 .queryOrdered(byChild: "timeStamp") 并且它工作正常:
Database.database().reference()
.child("favorite")
.child(uid) // TKAETTLWAuREMZXCvrVeZd8yIPw2
.queryOrdered(byChild: "timeStamp")
.queryLimited(toLast: 10)
.observeSingleEvent(of: .value, with: { [weak self](snapshot) in
当删除一个键,然后将相同的键添加回数据库,然后通过queryOrderedByKey() 查询时,一定会导致某种内部问题,不仅会弄乱键,还会弄乱整个引用。我认为在我删除密钥之后会发生什么,无论内部跟踪机制将其从系统中擦除。当我重新添加它时,它不再是同一个键,而是一个普通的String,没有内部含义,这就是为什么说null。我要求它查询一些没有意义的东西。这是一个疯狂的猜测。
但我想知道为什么从未删除并重新添加到同一个引用的全新密钥会出现同样的问题?
这是@FrankvanPuffelen 在 cmets 中请求的代码:
这是发送/删除数据的vc。
1- sendDataToFirebase()
2- deleteDataFromFirebase()
3- sendDataToFirebase()
按这个顺序做
var someOtherId = "12345" // this id has nothing to do with firebase and might be something like "x778-248-000"
var snapKey: String?
var originalTimeStamp: Double?
func sendDataToFirebase() {
guard let uid = Auth.auth().currentUser?.uid else { return }
guard let fbKey = Database.database().reference().child("favorite").childByAutoId().key else { return }
let timeStamp = Date().timeIntervalSince1970
var favoriteDict = [String: Any]()
favoriteDict.updateValue(uid, forKey: "uid")
favoriteDict.updateValue(originalTimeStamp ?? timeStamp, forKey: "timeStamp")
var whichKeyToUse: String?
if let snapKey = self.snapKey {
whichKeyToUse = snapKey
} else {
whichKeyToUse = fbKey
}
var carDict = [String: Any]()
carDict.updateValue(originalTimeStamp ?? timeStamp, forKey: whichKeyToUse!)
let favoriteRef = "favorite/\(uid)/\(whichKeyToUse!)"
let carRef = "carType/\(someOtherId)/\(uid)"
var multiLocationDict = [String: Any]()
multiLocationDict.updateValue(favoriteDict, forKey: favoriteRef)
multiLocationDict.updateValue(carDict, forKey: carRef)
Database.database().reference().updateChildValues(multiLocationDict, withCompletionBlock: { (error, ref) in
if self.snapKey == nil {
self.snapKey = fbKey
}
if self.originalTimeStamp == nil {
self.originalTimeStamp = timeStamp
}
// if no error this 100% saves it the way it's supposed to
})
}
func deleteDataFromFirebase() {
guard let uid = Auth.auth().currentUser?.uid else { return }
guard let snapKey = self.snapKey else { return }
let favoriteRef = "favorite/\(uid)/\(snapKey)"
let carRef = "carType/\(someOtherId)/\(uid)"
var multiLocationDict = [String: Any]()
multiLocationDict.updateValue(NSNull(), forKey: favoriteRef)
multiLocationDict.updateValue(NSNull(), forKey: carRef)
Database.database().reference().updateChildValues(multiLocationDict, withCompletionBlock: { [weak self](error, ref) in
// if no error this 100% deletes what it's supposed to
})
}
2。这是读取数据的vc,这是一个完全不同的vc,问题出在哪里
func firstCheckIfCurrentUserExistsAtFavoriteRef() {
guard let uid = Auth.auth().currentUser?.uid else { return }
let favoriteRef = Database.database().reference()
.child("favorite")
.child(uid)
favoriteRef.observeSingleEvent(of: .value) { [weak self](snapshot) in
if !snapshot.exists() {
return
}
print(snapshot.key) // prints the key
print(snapshot.value) // *** the value prints fine here but in handlePagination it prints null ***
if snapshot.hasChildren() {
print("yay") // prints yay
} else {
print("nay")
}
self?.handlePagination(with: uid)
}
}
var startKey: String?
func handlePagination(with currentUserId: String) {
if startKey == nil {
Database.database().reference()
.child("favorite")
.child(currentUserId)
.queryOrderedByKey() // it works fine with this >>> .queryOrdered(byChild: "timeStamp")
.queryLimited(toLast: 10)
.observeSingleEvent(of: .value, with: { [weak self](snapshot) in
print(snapshot.key) // prints the uid
print(snapshot.value) // *** prints null but in firstCheckIfCurrentUserExistsAtFavoriteRef() it prints fine ***
if snapshot.hasChildren() {
print("yay")
} else {
print("nay") // prints nay
}
guard let children = snapshot.children.allObjects.first as? DataSnapshot else { return }
// ...
})
} else {
// it never makes it this far but it's the same code from above
Database.database().reference()
.child("favorite")
.child(currentUserId)
.queryOrderedByKey() // it works fine with this >>> .queryOrdered(byChild: "timeStamp")
.queryEnding(atValue: startKey!)
.queryLimited(toLast: 11)
.observeSingleEvent(of: .value, with: { [weak self](snapshot) in
}
我打电话给firstCheckIfCurrentUserExistsAtFavoriteRef()viewDidLoad
【问题讨论】:
-
这个描述听起来不像是我从实时数据库中看到的行为。你能展示一个任何人都可以运行来重现问题的sn-p代码吗?这可能应该包括删除/写入节点的代码,因为这些似乎是您问题的关键。
-
@FrankvanPuffelen 我添加了整个代码。并且所有内容都会被添加和删除,而正确的参考文献没有问题。除了问题中提出的奇怪问题之外,它完全按照我的预期工作。
-
您在任何地方都在使用
observeSingleEvent,这意味着听众不会保持活跃。你在哪里调用这些方法。另请注意,您现在共享了三个侦听器,而不仅仅是之前的一个。有没有办法construct a single code block that someone can run end to end to (reasonably reliably) reproduce the issue? -
我在 viewDidLoad 中调用 firstCheckIfCurrentUserExistsAtFavoriteRef。除此之外,我的代码在其他 vcs 中工作的问题。当我分页时,一切正常。这是用户在历史记录中检查的数据,因此无需使用 .observe,因为不会出现新数据。它只是在滚动时分页。
-
您是否启用了持久性?
标签: ios swift firebase firebase-realtime-database snapshot