如果 ref 不再存在,Swift -Firebase 如何触发 TransactionResult.abort()
Posted
技术标签:
【中文标题】如果 ref 不再存在,Swift -Firebase 如何触发 TransactionResult.abort()【英文标题】:Swift -Firebase how to trigger a TransactionResult.abort() if the ref no longer exists 【发布时间】:2020-10-24 20:10:07 【问题描述】:如果我想从数据库中检索一些数据,我可以使用snapshot.exists()
来检查它是否存在:
ref.observeSingleEvent(of: .value, with: (snapshot) in
if !snapshot.exists() return
但是在运行Transaction
时,我只是更新了一些不再存在的东西,而不是出现错误,它更新了我没想到的 ref。
1- Transaction 应该更新的子引用:
@posts
@postId_123 // this post has actually been deleted
-url: ...
-timeStamp: ...
-comments_count: 10
-2 用户可以在不实际查看的情况下删除其中一个 cmets。一旦发生这种情况,cmets_count 就会减少。
let postsRef = Database.database().reference().child("posts").child("postId_123").child("comments_count")
postsRef.runTransactionBlock( (mutableData: MutableData) -> TransactionResult in
var currentCount = mutableData.value as? Int ?? 0
mutableData.value = currentCount - 1
currentCount = mutableData.value as? Int ?? 0
if currentCount < 0
mutableData.value = 0
return TransactionResult.success(withValue: mutableData)
, andCompletionBlock: [weak self](error, completion, snap) in
if !completion || (error != nil)
print("The value wasn't able to update")
print(error?.localizedDescription as Any)
else
print("The value updated")
)
3- 问题是如果 postId_123 在 Transaction 运行之前被删除,上述 Transaction 会导致 postId_123 被放回帖子引用中:
@posts
@postId_123 // this postId has been been put back but should no longer exist
-comments_count: 0
如果 mutableData 的子级不再存在,我该如何运行 TransactionResult.abort()
?
let postsRef = Database.database().reference().child("posts").child("postId_123").child("comments_count")
postsRef.runTransactionBlock( (mutableData: MutableData) -> TransactionResult in
if !mutableData.exists() // *** this check isn't real and is used just as an example ***
return TransactionResult.abort() // this is real
var currentCount = mutableData.value as? Int ?? 0
// ...
)
【问题讨论】:
【参考方案1】:这是我发现触发中止的唯一方法。如果有人以其他方式发布,我将删除此答案。
首先要知道的是,要使此答案起作用,您尝试在其上运行 Transaction
的任何孩子都必须事先具有 值,并且不能为 nil 。例如,如果尝试在 post 上的 cmets_count 上运行 Transaction
,则在第一次创建帖子时,cmets_count 必须是与它一起创建并设置为 0(目前还没有 cmets)。 如果那里什么都没有,那么使用下面的这种方法cmets_count将永远不会更新:
var dict = [String: Any]()
dict.updateValue(postId_123, forKey: "postId")
dict.updateValue(0, forKey: "comments_count") // *** this is important ***
dict...
let postsRef = ...child("posts").child(postId_123)
postsRef.updateChildValues(dict)
然后,当尝试在 cmets_count 上运行 Transaction
时,如果值为 nil,则帖子被删除(这是假设没有其他方法可以删除cmets_count 而不是删除整个帖子)。如果是 nil 则运行 TransactionResult.abort()
。在completionBlock
中,您检查error
是否为nil
let postsRef = Database.database().reference().child("posts").child("postId_123").child("comments_count")
postsRef.runTransactionBlock( (mutableData: MutableData) -> TransactionResult in
// if nil then the post was deleted
let checkIfCountExists = mutableData.value as? Int
if checkIfCountExists == nil
return TransactionResult.abort()
// not nil then continue on
var currentCount = mutableData.value as? Int ?? 0
mutableData.value = currentCount - 1
currentCount = mutableData.value as? Int ?? 0
if currentCount < 0
mutableData.value = 0
return TransactionResult.success(withValue: mutableData)
, andCompletionBlock: [weak self](error, completion, snap) in
if !completion || (error != nil)
print("The value wasn't able to update")
print(error?.localizedDescription as Any)
if error == nil
print("*** transaction value is nil ***")
return
// there is a value there but something else went wrong so try again
else
print("The value updated")
)
【讨论】:
以上是关于如果 ref 不再存在,Swift -Firebase 如何触发 TransactionResult.abort()的主要内容,如果未能解决你的问题,请参考以下文章
Swift 3:当孩子存在时,FirebaseDB 返回 nil
Swift 是不是有类似“ref”关键字的东西强制参数通过引用传递?
facebook SDK [Firebase Ref.,Swift] 中缺少 FBSessionStateOpen