为啥我的闭包在我期望的时候没有被调用?

Posted

技术标签:

【中文标题】为啥我的闭包在我期望的时候没有被调用?【英文标题】:Why is my closure not called when I expect it to be?为什么我的闭包在我期望的时候没有被调用? 【发布时间】:2021-12-08 15:44:36 【问题描述】:

在学习 Swift 时,我从来没有真正理解过的一件事是闭包。我总是觉得和他们一起工作很困惑。

谁能解释一下我在下面的代码中做错了什么。

for id in myCircles
    var circleName = ""
    var circleCategory = ""
    var circleID = ""
            
            
            
    ref.child("\(id)").observeSingleEvent(of: .value, with:  snapshot in
        
        let value = snapshot.value as? NSDictionary
        circleName = value?["name"] as? String ?? ""
        circleCategory = value?["category"] as? String ?? ""
        circleID = value?["id"] as? String ?? ""
                
                
        self.defaults.setValue([circleName, circleID, circleCategory], forKey: "newestCircle"+"\(id)")

   )  error in
              
      
            
//the problem is that the part below gets executed before the closure, which is when the value should be added. The part below must be executed after the closure.
            
    let retrievedData = self.defaults.value(forKey: "newestCircle"+"\(id)") as? [String] ?? ["","",""]
    
    self.addCircle(circleName: retrievedData[0], circleID: retrievedData[1], circleCategory: retrievedData[2])
             
 

正如评论所说,我的 .observingSingeEvent 闭包是在闭包下方的代码之后调用的。它不仅在闭包下面的代码之后被调用,而且在整个 for 循环之后被调用,如果它在循环内部被调用的话,它会被调用多次。我不明白这是为什么,有人可以帮助我吗?

【问题讨论】:

这能回答你的问题吗? Wait for Firebase to load before returning from a function 看看我对this question的简短回答 【参考方案1】:

闭包只是匿名函数。没有区别

func sum(_ a: Int, _ b: Int) -> Int 
    a + b

let sum: (Int, Int) -> Int =  a, b in a + b 

这两个函数做的事情完全相同,将两个整数相加,但它们以不同的形式表示,一个作为函数,一个使用闭包语法,两者都是可以互换的。它们之间最大的区别在于函数是命名的,而闭包是匿名的。我们将闭包存储在一个名为 sum 的变量中,但闭包本身没有名称。

对于您的具体问题,我没有使用 Firebase,但发生的是这个电话

    ref.child("\(id)").observeSingleEvent(of: .value, with:  snapshot in
        
        let value = snapshot.value as? NSDictionary
        circleName = value?["name"] as? String ?? ""
        circleCategory = value?["category"] as? String ?? ""
        circleID = value?["id"] as? String ?? ""
                
                
        self.defaults.setValue([circleName, circleID, circleCategory], forKey: "newestCircle"+"\(id)")

   )  error in
              
      

正在异步执行。 ref.child.observeSingleEvent 将闭包作为参数并稍后调用它,这意味着闭包的执行与您的其余代码完全分开。这就是为什么您会看到打印不同步的原因,因为闭包是异步执行的。

顺便说一句,尽量避免使用NSDictionary,除非你绝对必须使用新的 Swift 并发特性来代替闭包。

【讨论】:

以上是关于为啥我的闭包在我期望的时候没有被调用?的主要内容,如果未能解决你的问题,请参考以下文章

ES6中let和闭包

闭包,string类,Array类

简单理解闭包;

Swift:为啥调用闭包函数到晚

为啥 @noescape 在需要时不会自动应用于 Swift 闭包?

回调函数和闭包