Swift 如何使用异步函数之外的值?

Swift 如何使用异步函数之外的值?,swift,function,asynchronous,Swift,Function,Asynchronous,最初的函数应该是这样的: func retrieveMonthlySpent(month:String, year:String) -> Double { FirebaseFunctions().retrieve(from: .expense, username: self.username as! String, returning: Expenses.self) { (expenses) in self.monthlyExpenses = expenses

最初的函数应该是这样的:

func retrieveMonthlySpent(month:String, year:String) -> Double {
    FirebaseFunctions().retrieve(from: .expense, username: self.username as! String, returning: Expenses.self) { (expenses) in
        self.monthlyExpenses = expenses
    }

    var sum:Double = 0
    for expense in self.monthlyExpenses{
        if expense.modificationDate.convertToMonth() == month && expense.expense && expense.modificationDate.convertToYear() == year {
            sum += expense.convertedAmount
        }
    }

    return sum
}
但由于Swift中同步功能的工作方式,每月费用值不会更新。因此,我尝试更改代码,以便将尽可能多的代码放入异步函数本身,结果如下所示:

func retrieveMonthlySpent(month:String, year:String) -> Double{
    FirebaseFunctions().retrieve(from: .expense, username: self.username as! String, returning: Expenses.self) { (expenses) in
        self.monthlyExpenses = expenses
        var sum:Double = 0
        for expense in self.monthlyExpenses{
            if expense.modificationDate.convertToMonth() == month && expense.expense && expense.modificationDate.convertToYear() == year{
                sum += expense.convertedAmount
            }
        }
    }
    return sum
}

但问题是现在sum的值是0,因为我在这个异步函数之外使用了一个变量。我已经看到这个问题在多个问题上被提出,但我在任何地方都找不到答案。此问题的解决方案是什么?如果调用异步API,则必须使用完成处理程序:

func retrieveMonthlySpent(month:String, year:String, success: @escaping (Double) -> Void) {
    FirebaseFunctions().retrieve(from: .expense, username: self.username as! String, returning: Expenses.self) { (expenses) in
        self.monthlyExpenses = expenses
        var sum:Double = 0
        for expense in self.monthlyExpenses{
            if expense.modificationDate.convertToMonth() == month && expense.expense && expense.modificationDate.convertToYear() == year{
                sum += expense.convertedAmount
            }
        }
        success(sum)
    }
}
您可以从当前控制器使用此方法,如下所示:

self.retrieveMonthlySpent(month: "", year: "") { (sum) in
            print(sum)
        }
Xviewcontroller().retrieveMonthlySpent(month: "", year: "") { (sum) in
            total = sum
        }
或者从其他ViewController,您可以这样使用:

self.retrieveMonthlySpent(month: "", year: "") { (sum) in
            print(sum)
        }
Xviewcontroller().retrieveMonthlySpent(month: "", year: "") { (sum) in
            total = sum
        }

为了更好地重用代码,您需要将此方法放在superviewcontroller或任何公共类中。

在获取数据时,将完成处理程序用作触发器更新UI

具有完成处理程序的设置函数:

func retrieveMonthlySpent(month:String, year:String, completion: ((Double) -> Void)? = nil) {
FirebaseFunctions().retrieve(from: .expense, username: self.username as! String, returning: Expenses.self) { (expenses) in
    self.monthlyExpenses = expenses
    var sum = 0.0
    for expense in self.monthlyExpenses {
        if expense.modificationDate.convertToMonth() == month && expense.expense && expense.modificationDate.convertToYear() == year {
            sum += expense.convertedAmount
        }
    }
    completion(sum)
  }
}
在viewController中使用它,例如:

func retrieveMonthlySpent(month:"05", year:"1996") { result in
      self.sumLabel.text = result
}

就像塔诺斯折断手指的方式一样简单:

好的,但是在第二个视图控制器中,我会不会遇到一个问题,我不能在完成处理程序之外使用变量total?你不能在block man之外使用这个变量