什么是Swift References的_下划线代表?

时间:2014-06-26 18:11:11

标签: objective-c function swift declaration

在Apple的文档的参考部分中,有很多此类事件的实例:

  

func runAction(_ action : SKAction!)

Objective-C'等同于'这是:

  

- (void)runAction:(SKAction *) action

令我感到非常重要的是(在Swift参考文献中)在下划线和"动作之后有一个空格"用斜体字书写。

但我无法弄清楚这是想传达什么。所以也许问题是......是否有参考文献中使用的约定?

- 这是我在此对下划线用法的引用中引用的页面: https://developer.apple.com/documentation/spritekit/sknode#//apple_ref/occ/instm/SKNode/runAction

更新

Swift 3对如何使用和命名函数/方法参数名称和参数标签进行了一些更改。这会对这个问题及其答案产生影响。 @Rickster做了一个很棒的工作,回答了关于_underscores的不同问题,这些问题清除了大部分内容,在这里:Why do I need underscores in swift?

7 个答案:

答案 0 :(得分:106)

这两个答案都是正确的,但我想澄清一点。

_用于modify external parameter name behavior for methods

在文档的Local and External Parameter Names for Methods部分,它说:

  

默认情况下,Swift在方法中为第一个参数名称提供一个本地参数名称,默认情况下提供第二个和后续参数名称本地和外部参数名称

另一方面,默认情况下,函数不具有外部参数名称。

例如,我们在课程foo()中定义了此Bar方法:

class Bar{
    func foo(s1: String, s2: String) -> String {
        return s1 + s2;
    }
}

当您致电foo()时,会将其称为bar.foo("Hello", s2: "World")

,您可以在声明它的_前面s2覆盖此行为。

func foo(s1: String, _ s2: String) -> String{
    return s1 + s2;
}

然后,当您拨打foo时,可以简单地调用bar.foo("Hello", "World"),而不使用第二个参数的名称。

回到您的情况,runAction是一种方法,因为它显然与类型SKNode相关联。因此,在参数_之前加action可以让您在没有外部名称的情况下调用runAction

Swift 2.0更新

在本地和外部参数名称声明方面,函数和方法现在以相同的方式工作

现在默认使用外部参数名调用函数,从第2个参数开始。此规则仅适用于纯Swift代码。

因此,通过在功能前面提供_,调用者不必指定外部参数名称,就像您对所做的那样>方法

答案 1 :(得分:84)

下划线是用于表示丢弃值的通用标记。

在这种特定情况下,这意味着该函数将被调用为runAction(argument)而不是runAction(action:argument)

在其他情况下,它具有其他类似含义,例如在:

for _ in 0..<5 { ... }

这意味着我们只想执行5次块,而不关心块内的索引。

在此背景下:

let (result, _) = someFunctionThatReturnsATuple()

这意味着我们不关心元组的第二个元素是什么,只关注第一个元素。

答案 2 :(得分:13)

参数声明前面的标识符定义外部参数名称。这是调用者在调用函数时必须提供的名称:

func someFunction(externalParameterName localParameterName: Int)

如果您没有自己提供外部名称,Swift会为您定义的任何默认参数提供自动外部名称。使用外部参数名称的下划线可以选择此行为:

  

您可以在定义参数时通过编写下划线(_)而不是显式外部名称来选择退出此行为。

您可以在具有默认值的参数的外部名称 here部分中详细了解此行为。

答案 3 :(得分:11)

自Swift 3 默认需要所有参数标签。

您可以强制IDE使用_隐藏参数标签。

func foo(a: String) {
}

func foo2(_ a: String) {
}

名为foo(a: "abc")foo2("abc")

  

注意:仅当a(外部)参数标签(内部)变量名称时才能使用此选项同时。它是等效的 - func foo(a a: String)不会接受_

为什么Apple使用它?

您可以看到Apple正在API中使用它。 Apple的库仍然是用Objective-C 编写的(如果没有,它们共享相同的函数名,它们是为Objective-C语法设计的)

applicationWillResignActive(_ application: UIApplication)之类的功能会有冗余参数名称application,因为其中已经有应用程序的函数名称。

你的例子

func runAction(_ action: SKAction!)将被称为,而不是它的_标记为runAction(action:)。 参数名称action冗余,因为函数名称中已有一个。这就是它的目的和原因。

答案 4 :(得分:10)

我认为这迫使Swift中的一个约定使它更接近于Objective-c,它更好地匹配了cocoa约定。在objc中,你不要(外部)命名你的第一个参数。相反,按照惯例,您通常在方法名称的后半部分包含外部名称,如下所示:

- (void)myFancyMethodWithFirstName:(NSString *)aFirstName lastName:(NSString *)aLastName;

[someInstance myFancyMethodWithFirstName:@"John" lastName:@"Doe"];

要使Swift api调用与objc一致,您需要抑制第一个参数的外部参数名称。

func myFancyMethodWithFirstName(_ firstName:String, lastName:String);

someInstance.myFancyMethodWithFirstName("John", lastName:"Doe")

答案 5 :(得分:5)

实际上,用于定义方法的实际代码与Apple的文档中的方法声明之间存在差异。我们来看看 UIControl - addTarget:action:forControlEvents:方法,例如,真正的代码是:  enter image description here

但在文档中,它看起来像这样(在目标之前注意_): enter image description here

在实际代码中,_用于生成第二个或后续参数的外部名称 在调用方法时不显示,而在文档中,_在参数的本地名称之前_表示当您调用方法或函数时,不应提供外部名称。

默认情况下调用函数时没有外部名称,除非您提供自己的函数或添加#之前(没有空格)参数的本地名称,例如,这就是我们使用 dispatch_after : enter image description here

在文档中,它看起来像这样(注意三个_): enter image description here

函数声明的约定与我对方法的描述相同。

答案 6 :(得分:1)

更直观。

enter image description here

正如您所见,_只是省略了本地参数名称。