什么是下划线代表在Swift参考?

在苹果的文档的参考部分中有很多这样的事情:

func runAction(_ action : SKAction!)

Objective-C的“等值”是这样的:

- (void)runAction:(SKAction *) action

这让我觉得(在Swift引用中)在下划线之后有一个空格,而“action”用斜体字写的可能很重要。

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

– 这里是我引用这个引用下划线使用的页面: https : //developer.apple.com/documentation/spritekit/sknode#//apple_ref/occ/instm/SKNode/runAction

更新

Swift 3对如何使用和命名函数/方法参数名称和参数标签做了一些更改。 这对这个问题及其答案有影响。 @Rickster在解决这个问题的函数中做了一个关于_underscores的不同问题,这个问题做得非常出色: 为什么我需要快速的下划线?

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

_用于修改方法的外部参数名称行为 。

在文档的“ 方法的本地和外部参数名称”部分,它说:

Swift在默认情况下给方法中的第一个参数名称一个本地参数名称,并且默认给出第二个和后续的参数名称本地和外部参数名称

另一方面,默认的函数没有外部参数名称。

例如,我们在Bar类中定义了这个foo()方法:

 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是一个方法,因为它显然与SKNodetypes相关联。 因此,放置一个_之前的参数action可以让你在没有外部名字的情况下调用runAction

更新Swift 2.0

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

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

因此,通过在函数前面提供一个_ ,调用者不必指定外部参数名称,就像您为某个方法所做的一样。

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

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

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

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

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

在这种情况下:

 let (result, _) = someFunctionThatReturnsATuple() 

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

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

 func someFunction(externalParameterName localParameterName: Int) 

如果你自己没有提供外部的名字,Swift为你定义的任何默认参数提供了一个自动的外部名字。 对外部参数名称使用下划线select此行为:

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

您可以在这里阅读关于这个行为的更多信息。

由于Swift 3 默认情况下需要所有参数标签。

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

 func foo(a: String) { } func foo2(_ a: String) { } 

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

注意:只有当(外部)参数标签(内部)variables名称同时出现时,才可以使用此参数 。 它是等效的 – func foo(aa: String)不会接受_

为什么苹果使用它?

你可以看到苹果正在跨API使用它。 Apple的库仍然是用Objective-C语言编写的(如果不是的话,它们共享相同的函数名称,这些名称是为Objective-C语法devise的)

applicationWillResignActive(_ application: UIApplication)这样的函数将会有冗余参数名称的application ,因为已经有了应用程序的函数名。

你的例子

func runAction(_ action: SKAction!)会被调用, 而不会_ runAction(action:)这样的标记。 参数名称action将是多余的,因为函数名称中已经有一个。 这是目的,为什么它在那里。

我认为这迫使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") 

实际上,用于定义方法的实际代码与Apple文档中的方法声明是有区别的。 我们以UIControladdTarget:action:forControlEvents:方法为例,实际的代码是: 在这里输入图像描述

但是在文档中,它看起来像这样(注意_在目标之前): 在这里输入图像描述

在实际的代码中,当调用一个方法时,_用于使第二个或后续参数的外部名称不出现,而在docs中,_在参数的本地名称之前指示当您调用方法或函数时,不应该提供外部名称。

当一个函数被默认调用的时候没有外部名字,除非你提供了你自己的或者在之前(没有空格)加上一个参数的本地名字,例如,这是我们如何使用dispatch_after在这里输入图像描述

在文档中,它是这样的(注意三个): 在这里输入图像描述

函数声明的约定和我所描述的方法是一样的。

只是更直观。

在这里输入图像描述

正如你所看到的,只是省略一个本地参数名称。