【问题标题】:Assigning value to inout parameters within closure in Swift 3在 Swift 3 的闭包中为 inout 参数赋值
【发布时间】:2017-06-02 00:23:39
【问题描述】:

当我在完成块内尝试为函数参数赋值时出现错误,我收到一个错误,内容为 'escaping closures can only capture inout parameters explicit by value'。

我该如何解决这个问题?非常感谢任何提示!

func fetchCurrentUser(user: inout User? ) {
    self.fetchUser(withId: AuthProvider.sharedInstance.currentUserId(), completionHandler: {
        fetchedUser in
        guard let newUser = fetchedUser else { return }
        user = newUser // error Here
    })
}

【问题讨论】:

  • 您可能还会发现this answer 很有帮助。
  • This solution 展示如何在转义闭包中修改传递引用变量。

标签: swift closures completionhandler inout


【解决方案1】:

这不起作用,因为您使用了完成处理程序。 self.fetchUser 将(几乎)立即返回,并且只要后台工作(很可能是网络请求)完成,就会执行完成处理程序。

您的函数 fetchCurrentUser 调用 self.fetchUser 并返回,因此它会在完成块执行之前返回。

您不能在转义闭包上使用 inout 参数(这也是错误消息告诉您的内容)。转义闭包是一个闭包,它将在您传入的函数返回之后执行。

您可以重写您的函数以也使用完成处理程序,或者更改您的函数以等待完成处理程序在结束 fetchCurrentUser 函数之前运行。但是对于第二种方法,请注意,这也会阻止函数的调用者执行任何其他操作。

【讨论】:

  • 感谢您的洞察力。我计算出 fetchedUser 可以访问的时间,然后 inout 参数(用户)将被分配该值。
【解决方案2】:

我建议这个重构:

func fetchCurrentUser(callback: @escaping (User) -> ()) {
    self.fetchUser(withId: AuthProvider.sharedInstance.currentUserId(), completionHandler: {
        fetchedUser in
        guard let newUser = fetchedUser else { return }
        callback(newUser)
    })
}

或者如果您希望 fetchCurrentUser 是同步的,您可以使用信号量

【讨论】:

  • 我建议将闭包参数设为可选,例如func fetchCurrentUser(callback: @escaping (User?) -> Void) { ... },如果失败,请使用 nil 调用关闭。您真的希望调用者知道是否有错误。关于同步建议,这几乎总是一个坏主意,通常是根深蒂固的设计缺陷的代码气味。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-01
  • 2021-06-29
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 2017-12-10
相关资源
最近更新 更多