Xcode 8:函数类型不能有参数标签破坏我的构建

Xcode 8 :function types cannot have argument label breaking my build

似乎出于某种原因 Swift 已选择通过强制用户删除完成处理程序参数标签来降低其中编码的可读性。我已经阅读了 Swift 的讨论,但仍然认为这是一个错误。至少他们可以将其设为可选。

使用 Xcode 8 构建时 - 有没有办法强制编译器使用 Swift 2.3,这样我就不会再收到这些错误了? 我已经更新了使用旧版 Swift 的选项(在构建设置下) 但我似乎仍然收到此错误:

Function types cannot have argument label 'isloggedIn'; use '_' instead

如何在我的完成处理程序中保留我的标签?

Swift 设计者决定禁止函数类型的参数标签。

这里解释一下原因:https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md

这是一个令人沮丧且值得怀疑的选择,因为禁止参数标签使得更容易错误地调用闭包,这似乎比简化语言的类型系统更重要。

可用性 > 意识形态。

要考虑的解决方法。你不能这样做:

func doStuff(completion: (foo: Int, bar: String) -> Void) {
    ...
    completion(foo: 0, bar: "")
}

...但你可以这样做:

func doStuff(completion: ((foo: Int, bar: String)) -> Void) {
    ...
    completion((foo: 0, bar: ""))
}

即你的闭包有一个未命名的参数,它是一个元组,在本例中为 (foo: Int, bar: String).

它以自己的方式丑陋,但至少你保留了参数标签。

根据以上信息 - 似乎真正解决此问题并确保其性能的唯一方法是提出一项提案 使参数标签可选,以期:

  1. 提高开发速度(没有参数标签,每次我们放入完成处理程序时都需要我们向上滚动到方法的顶部。
  2. 减少错误:(我已经遇到过一些由于不正确的完成处理程序条目导致的错误,尤其是那些需要布尔值的错误)
  3. 使代码在团队成员之间更具可读性。并非每个人都只有一名团队成员,因此必须能够轻松获取其他人的代码。
  4. 最后,良好的编程习惯意味着解决方案应该看起来与正在开发的实际项目一样。 completionhandler: (newvalues, nil)completionhandler(results: newValue, error:nil)
  5. 相比,看起来不太像被管理的项目

I would love for people reading this to share their feedback/ comments on this below before I submit it so I can show there are others that support this.

编辑: 我已经在这里提交了音调: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161010/028083.html 这似乎已经达成一致。看起来它会发生,但讨论的是这是否作为 Swift 4 改进(极有可能)提交

半解决方法,注意 _

completion: (_ success: Bool) -> Void

您必须使用 _ 使您的参数未命名,这很不幸。我建议不要将 _ 添加到每个参数然后盲目地调用您的函数,而是创建一个包装器对象。

由于丢失函数类型的命名参数会带来更大的风险,即您将使用错误的值调用函数,我建议将参数包装在一个结构中,并将其作为函数的唯一参数。

这样你结构的字段就被命名了,而且只有一种类型的值可以传递给你的函数。这比我们能够命名函数的参数更麻烦,但我们不能。至少这样你会更安全,也不会觉得脏。

struct LineNoteCellState {

    var lineNoteText: String?
    var printOnInvoice = false
    var printOnLabel = false
}

这是一个使用它的例子:

cell.configure(editCallback: { (_ state: LineNoteCellState) in

    self.lineNoteText = state.lineNoteText
    self.printOnInvoice = state.printOnInvoice
    self.printOnLabel = state.printOnLabel
})