在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?
答案 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正在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:方法,例如,真正的代码是:
但在文档中,它看起来像这样(在目标之前注意_):
在实际代码中,_用于生成第二个或后续参数的外部名称 在调用方法时不显示,而在文档中,_在参数的本地名称之前_表示当您调用方法或函数时,不应提供外部名称。
默认情况下调用函数时没有外部名称,除非您提供自己的函数或添加#之前(没有空格)参数的本地名称,例如,这就是我们使用 dispatch_after :
在文档中,它看起来像这样(注意三个_):
函数声明的约定与我对方法的描述相同。
答案 6 :(得分:1)