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


74

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

使用Xcode 8进行构建时-是否有一种方法可以强制编译器使用Swift 2.3,因此我不再遇到这些错误?我已经更新了使用旧版Swift的选项(在构建设置下), xcode中的旧版支持 但仍然出现此错误:

函数类型不能带有参数标签“ isloggedIn”;使用'_'代替

错误Xcode 8

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


看起来这只是在说您不能使用名为“错误”的参数,而不是说您不能给它命名。您是否尝试过将“错误”重命名为其他内容?
dudeman's

23
@dudeman Swift 3明确禁止在函数类型中使用参数标签。选择可疑,非常令人沮丧。
Crashalot

17
令人沮丧和烦恼。我正在淘汰好的代码,以使其不那么易读,并且容易出错
UKDataGeek

13
我绝对讨厌这种变化。
UKDataGeek

5
Swift 3似乎在哲学上似乎太无懈可击了,人类历史告诉我们这不是处理事情的最有效方法。绝对讨厌Swift 3中的许多更改
funct7 '16

Answers:


99

Swift设计师决定禁止为函数类型使用参数标签。

原因在这里说明:https : //github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md

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

可用性>意识形态。


6
我同意这一点-但这并不是真正的解决方案。我建议我们努力提出一项建议,以使该建议成为可能。
UKDataGeek '16

已将其添加为当前解决方案,其真正的解释非常清楚
UKDataGeek

16
仍然没有我在Swift 3.1中建议的解决方案的迹象-希望我们能在Swift 4.之前得到它。
UKDataGeek '16

@Crashalot但是,如何通过这些函数传递参数呢?
MatterGoal

@matterGoal是什么意思?
UKDataGeek '16

23

要考虑的解决方法。您不能:

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
任何想法如何使typealias都可以使用public typealias ImageDataCompletion =((((imgData imgData:Data ?, _ err:MYGR8TErrorClass?))-> Void)给出:...元组元素不能有两个标签!wtf ????
安东·特罗帕什科

@AntonTropashko:(((imgData imgData: Data?, _ err: MYGR8TErrorClass?)) -> Void)应该是(((imgData: Data?, err: MYGR8TErrorClass?)) -> Void)。您正在尝试两次标记元组元素
sam-w

2
此解决方案的局限性是元组不能具有单个值。
标记

11

根据上述信息,看来解决此问题并确保其性能的唯一方法是提出一项建议,以使参数标签为可选项,以期:

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

我希望阅读此书的人在提交此书之前可以在下面分享他们对此的反馈/评论,这样我可以表明还有其他人对此表示支持。

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


2
好的,自从您提出要求后,让我发泄:开源猴子不会第一次(在有价值的贡献之前就可以使用)弄糟了。阿们
安东·特罗帕什科

@AntonTropashko支持在堆栈溢出时发泄-希望您感觉更好??
UKDataGeek

也支持答案!终于解脱了!认真:否
Anton Tropashko

@MobileBloke的现状如何?我看不到它用的语言……
frangulyan

否-看起来它已经被取消了优先级。它仍然很烦人。
UKDataGeek

9

您必须使用_来使您的参数不命名,这很不幸。建议不要制作一个包装对象,而不是在每个参数上加上_然后盲目地调用您的函数。

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

这样,您的struct字段就会被命名,并且只有一种类型的值可以传递到函数中。比我们能够命名函数的参数要麻烦得多,但不能。至少这样,您会更安全,也不会感到肮脏。

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
})

4

半解决方法,请注意_

completion: (_ success: Bool) -> Void

1
对于我来说,这似乎并不自动完成-成功参数之前的下划线功能是什么?
UKDataGeek
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.