当您在 Swift 中有嵌套函数时,如何将布尔值返回给外部函数?

Posted

技术标签:

【中文标题】当您在 Swift 中有嵌套函数时,如何将布尔值返回给外部函数?【英文标题】:How to return a bool to the outside function when you have nested functions in Swift? 【发布时间】:2017-03-29 23:42:13 【问题描述】:

所以我有一个函数,它有一个连接到 Firebase 数据库的内部函数。该函数返回一个布尔值,但我需要根据 Firebase 数据库中的内容返回 true 或 false。所以基本上我需要在 Firebase 函数内部返回 true 或 false 问题是当我实际上试图返回外部函数时,它认为我正在尝试返回 Firebase 函数,一个简单的例子就是这样

func someOtherFunc(name: String, lastname: String)



func someFunc(name: String, lastname: String) -> bool 
    someOtherFunc(name: name, lastname: lastname) 
        if name == "George" 
        return true


         else 
        return false // will not work because some other func does not return a value
        


    

这是我需要修复的代码,它比上面的函数稍微复杂一点,因为内部 Firebase 函数是异步运行的(在后台),所以函数内的所有代码都需要同步运行才能返回正确的值

这是我的功能

func takeAwayMoney(_ howMuch: String) -> Bool
        if let notMuch = Int(howMuch) 

            let userID = FIRAuth.auth()?.currentUser?.uid
            datRef.child("User").child(userID!).observeSingleEvent(of: .value, with:  (snapshot) in
                // Get user value
                let value = snapshot.value as? NSDictionary
                let money = value?["money"] as? String ?? ""

                //convert money to int
                if let conMoney = Int(money) 
                    var conMoreMoney = conMoney
                    if conMoreMoney < notMuch 
                        print(" sorry you don't have enough money")
                        return false
                     else 
                        conMoreMoney -= notMuch
                        let values = ["money": String(conMoreMoney)]

                        //update the users money
                        self.datRef.child("User").child(userID!).updateChildValues(values)
                        return true //doesn't work because of example above
                    

                

                // ...
            )  (error) in
                print(error.localizedDescription)
            
        
    

此代码无法编译,因为主函数没有返回值。

我知道解决这个问题的真正困难的方法是在函数顶部初始化值,这将是用户的钱,然后在调度它几秒钟后检查它,然后你可以返回值,但是我知道肯定有其他方法,因为这种方法会导致很多问题。

【问题讨论】:

Can Swift return value from an async Void-returning block?的可能重复 Firebase 是异步的,尝试返回值(即使有额外的完成句柄、线程等)确实会使事情变得过于复杂,并且需要大量额外的代码。简单的解决方案是重新考虑为什么要返回 true 或 false,以及返回的值如何影响其余代码。在这种情况下,代码会检查用户有多少钱并据此采取行动——返回的值没有被使用。更新 UI,然后仍处于关闭状态,如果有则继续下一步。这将提供流畅的用户体验。 【参考方案1】:

根本原因是takeAwayMoney是同步的,但它使用的是异步的observeSingleEvent

解决这个问题的“正确”方法是让 takeAwayMoney 返回 Void,但采用一个完成函数,它会异步为您提供 bool,如下所示:

func takeAwayMoney(_ howMuch: String, completion: @escaping (Bool)->()) -> Void 

/// When you want to "return" the bool, call the completion. e.g.:
// ...
                if conMoreMoney < notMuch 
                    print(" sorry you don't have enough money")
                    completion(false)
                    return // if you want to stop processing
                
// ...


如果您无法做到这一点,那么 takeMoney 需要等待完成,然后您使用信号量让它们相互通信。你不只是等待几秒钟。举个例子:

Semaphores to run asynchronous method synchronously

【讨论】:

这种问题已经被问过很多很多次了。最好作为一个骗子关闭而不是发布另一个答案。 好的,但是当我调用函数时,这会带来另一个问题,类似于 takeAwayMoney("20", completion: (result: Bool) in guard let returnedResult = result else return //这部分是与函数同步运行还是与主线程同步运行?)我需要知道将依赖于完成时返回的布尔值的代码放在哪里。 @LouFranco 如果您最终需要使其同步,那么您需要查看重复的问题或我发布的问题。 被observeSingleEvent响应的线程调用。如果您需要它作为主线程,请使用 dispatch_async 到主线程来执行此操作。一切都将是异步的。 你能告诉我如何使用 firebase 同步运行代码

以上是关于当您在 Swift 中有嵌套函数时,如何将布尔值返回给外部函数?的主要内容,如果未能解决你的问题,请参考以下文章

当您在循环中迭代数组时,如何知道数组中是否不存在更多值

当您在 postgres-XL 中有多个协调器时,您是不是有任何浮动 ip 重定向到一个协调器?

当您在 php 中调用函数时,内部会发生啥

当您在情节提要中“因特性而异”时,为啥此自动布局扩展会失败?

当您在 main 中动态分配内存时,如何处理函数中的 assert()?

如何更改 Swift 类的命名空间?