什么()在Swift中意味着什么?

时间:2016-10-05 12:51:46

标签: swift

我在Swift 3

中有以下功能
func fetchOrders(_ completionHandler: (_ orders: [Order]) -> Void)
  {
    ordersStore.fetchOrders { (orders: () throws -> [Order]) -> Void in
      do {
        let orders = try orders()
        completionHandler(orders)
      } catch {
        completionHandler([])
      }
    }
  }
  1. _ completionHandler中的fetchOrders参数是什么意思?
  2. (orders: () throws -> [Order])是什么意思?
  3. PS:我是iOSSwift

    的新手

3 个答案:

答案 0 :(得分:8)

这里有很多,所以我们一次打破一件:

func fetchOrders(_ completionHandler: (_ orders: [Order]) -> Void)
  • 这是一个名为fetchOrders的函数。
  • 它有一个参数(completionHandler)并且不返回任何内容。
  • 第一个_表示没有"外部名称"第一个参数。也就是说,你不必标记它(事实上,你不能)。 (由于微妙的原因,这里并不重要,我相信作者在那里使用_时犯了一个错误,我不会这样做。)
  • completionHandler是"内部名称,"函数内部调用了什么参数。
  • completionHandler的类型为(_ orders: [Order]) -> Void。我们现在打破这种局面。
    • 此值是一个闭包,它接受[Order]Order数组)并返回Void。非正式地,这意味着"什么都不返回"但字面意思是它返回空元组()
    • _ orders:语法实际上是评论。原则上_是一个外部名称(但它是闭包的唯一合法外部名称),而orders是一个内部名称,但实际上,闭包参数没有名称以任何有意义的方式,所以这纯粹是信息性的。
    • 我认为这是关闭参数注释系统的一个不好用法。由于orders告诉我们的不过是[Order],我会省略它,并将类型设为([Order]) -> Void

现在我们转向下一行:

ordersStore.fetchOrders { (orders: () throws -> [Order]) -> Void in
  • 这会调用fetchOrders上的ordersStore方法。我们可以从这段代码中看出fetchOrders采用了一个闭包参数。这被称为"尾随封闭" Swift中的语法,这就是为什么我不会使用_作为闭包的原因。使用尾随闭包语法,不需要参数的外部名称。
  • 作者提供了类型信息,这可能不是必要的,但无论如何我们都可以探索它。这可能只是写成{ orders in,但读者可能会对这个有点不寻常的代码感到惊讶。
    • 我们已经传递了一个名为orders的闭包,它不接受任何操作并返回[Order]或抛出错误。基本上这是说fetchOrders可能失败的一种方式。
    • 作者正在解决Swift的throws系统中的尴尬问题,该系统没有自然的方式来表达可能失败的异步操作。这是解决它的一种方法;你通过投掷(即可能失败)的功能。我不赞成这种方法,我赞成在这种情况下使用Result枚举,因为我认为它可以更好地扩展并避免可能的意外副作用,但这是一个值得商榷的问题(并且Swift社区没有& #39;我真的决定如何处理这个常见问题。)

这一切都引导我们:

  do {
    let orders = try orders()
    completionHandler(orders)
  } catch {
    completionHandler([])
  }
  • 这是评估orders闭包的地方。 (这非常重要;如果orders有副作用,这就是它们发生的时间,这可能与预期的队列不同。这是我不喜欢这种模式的一个原因。 )如果闭包成功,我们返回结果,否则我们会在[]下面返回catch
    • 在此特定的情况下,throws方法略显愚蠢,因为它甚至在没有日志消息的情况下默默地展平为[]。如果我们不关心错误,那么失败应该刚刚返回[]开始而不是与throws混淆。但是其他呼叫者可能会检查错误。
  • 在任何一种情况下,我们都会使用我们的结果调用completionHandler闭包,将其链接回原始调用者。

这个do / catch块可以更简单地写成:

let completedOrders = try? orders() ?? []
completionHandler(completedOrders)

通过将错误转换为可选错误,我们更清楚地忽略了错误,并避免了对completionHandler调用的代码重复。

(我只是添加额外的let绑定,以使代码更容易阅读;不需要它。)

答案 1 :(得分:2)

completionHandler参数表示期望参数(名为completionHandler)必须是一个获取Order个对象列表且不返回任何值的函数。

答案 2 :(得分:2)

completionHandler是变量名。在此特定示例中,此变量是callback。你知道是一个回调函数,因为(orders: [Order]) -> Void是它的数据类型;在这种特殊情况下,所述数据类型是一个函数,它接收变量Order中的_orders个对象数组,并且没有返回值(Void部分)。

TL; DR:

  1. 它是变量名,类型为:
  2. 函数,它接收Order数组作为参数并充当回调函数。