Firebase child 删除一个键然后将其添加回来后查询为零
Firebase child query coming up nil after deleting a key then adding it back
我 运行 下面的代码和使用打印语句数据库说 children 是 null
但在数据库中肯定有一些东西:
我唯一能想到的就是让用户删除一条消息(通过删除 -LoyeLv..
. 键),但如果他们想将其添加回来,他们可以。我保留已删除密钥的副本并将其发送回数据库,以便消息仍然同步。唯一的问题是,即使我不这样做(在我的例子中)并且我删除了消息,回来并用全新的密钥制作一个全新的消息,它仍然显示为 null?
尽管那里有 children 这怎么可能? 顺便说一句,这是我第一次遇到这种情况。
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")
}
我想删除那个 ref 的密钥比添加相同的密钥比再次删除它比添加一个全新的密钥会以某种方式关闭数据库吗?
再次更新 而不是使用 .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 在评论中要求的代码:
这是vc即sends/deletes的数据。
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
}
我在viewDidLoad
中调用firstCheckIfCurrentUserExistsAtFavoriteRef()
我之前在持久性打开时看到过这个问题 - 问题是数据部分同步但不完全同步。
要进行快速测试,请尝试关闭持久性并重新运行 查询。
Database.database().isPersistenceEnabled = false
这显然不是一个长期的解决方案,只是为了测试。
如果要使用持久化,还需要确保数据保持最新且始终同步。这是代码
let postsRef = Database.database().reference(withPath: "posts")
postsRef.keepSynced(true)
The Firebase Realtime Database client automatically downloads the data
at these locations and keeps it in sync even if the reference has no
active listeners. You can turn synchronization back off with the
following line of code
postsRef.keepSynced(false)
我 运行 下面的代码和使用打印语句数据库说 children 是 null
但在数据库中肯定有一些东西:
我唯一能想到的就是让用户删除一条消息(通过删除 -LoyeLv..
. 键),但如果他们想将其添加回来,他们可以。我保留已删除密钥的副本并将其发送回数据库,以便消息仍然同步。唯一的问题是,即使我不这样做(在我的例子中)并且我删除了消息,回来并用全新的密钥制作一个全新的消息,它仍然显示为 null?
尽管那里有 children 这怎么可能? 顺便说一句,这是我第一次遇到这种情况。
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")
}
我想删除那个 ref 的密钥比添加相同的密钥比再次删除它比添加一个全新的密钥会以某种方式关闭数据库吗?
再次更新 而不是使用 .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 在评论中要求的代码:
这是vc即sends/deletes的数据。
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
}
我在viewDidLoad
firstCheckIfCurrentUserExistsAtFavoriteRef()
我之前在持久性打开时看到过这个问题 - 问题是数据部分同步但不完全同步。
要进行快速测试,请尝试关闭持久性并重新运行 查询。
Database.database().isPersistenceEnabled = false
这显然不是一个长期的解决方案,只是为了测试。
如果要使用持久化,还需要确保数据保持最新且始终同步。这是代码
let postsRef = Database.database().reference(withPath: "posts")
postsRef.keepSynced(true)
The Firebase Realtime Database client automatically downloads the data at these locations and keeps it in sync even if the reference has no active listeners. You can turn synchronization back off with the following line of code
postsRef.keepSynced(false)