【问题标题】:How to return a bool to the outside function when you have nested functions in Swift?当您在 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)
            }
        }
    }

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

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

【问题讨论】:

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

标签: ios swift firebase firebase-realtime-database


【解决方案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 同步运行代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
  • 2021-01-05
  • 1970-01-01
  • 2013-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多