如果 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

从 Firebase 获取文档,但如果它们已经显示 - 不再显示

如果文件不再存在,如何卸载 Windows 服务?

如果文件不再存在,如何卸载 Windows 服务?