Swift:调用中缺少参数标签“ xxx”


73
func say(name:String, msg:String) {
    println("\(name) say \(msg)")
}

say("Henry","Hi,Swift")  <---- error because missing argument label 'msg' in call

我需要用

   say("Henry",msg:"Hi,Swift")

为什么呢 如果我在func中放置了两个以上的var,以便我在调用此func时需要写var名​​称而不是first var,
那确实很麻烦,并且在iBook Swift教程中看不到任何解释。


2
您的函数名称为“ say”,但您正在调用sayHello?
山姆B


我已经看到了这个问题,但并不能解决我的问题
henry4343 2014年

这是方法吗?(具有类功能的函数吗?)
Logan 2014年

Answers:


71

一个可能的原因是它实际上是一种方法。方法很偷偷摸摸,它们看起来像常规函数,但是它们的行为方式不同,让我们来看一下:

func funFunction(someArg: Int, someOtherArg: Int) {
    println("funFunction: \(someArg) : \(someOtherArg)")
}

// No external parameter
funFunction(1, 4)

func externalParamFunction(externalOne internalOne: Int, externalTwo internalTwo: Int) {
    println("externalParamFunction: \(internalOne) : \(internalTwo)")
}

// Requires external parameters
externalParamFunction(externalOne: 1, externalTwo: 4)

func externalInternalShared(#paramOne: Int, #paramTwo: Int) {
    println("externalInternalShared: \(paramOne) : \(paramTwo)")
}

// The '#' basically says, you want your internal and external names to be the same

// Note that there's been an update in Swift 2 and the above function would have to be written as:

func externalInternalShared(paramOne paramOne: Int, #paramTwo: Int) {
    print("externalInternalShared: \(paramOne) : \(paramTwo)")
}

externalInternalShared(paramOne: 1, paramTwo: 4)

现在是有趣的部分,在类内部声明一个函数,而不再是一个函数……它是一个方法

class SomeClass {
    func someClassFunctionWithParamOne(paramOne: Int, paramTwo: Int) {
        println("someClassFunction: \(paramOne) : \(paramTwo)")
    }
}

var someInstance = SomeClass()
someInstance.someClassFunctionWithParamOne(1, paramTwo: 4)

这是方法行为设计的一部分

苹果文档:

具体来说,Swift默认为方法中的第一个参数名称提供一个本地参数名称,默认情况下为第二个及后续参数名称提供本地和外部参数名称。该约定与您编写Objective-C方法所熟悉的典型命名和调用约定相匹配,并且无需限定参数名称即可进行表达性方法调用。

注意自动完成: 在此处输入图片说明


有趣的是,在Playground中不提供第二个参数的名称的方式似乎效果很好!
user1107173

1
@ user1107173-这是因为它不在类的上下文中。如果将其放在类中,它将提供第二个参数的名称。游乐场与它没有任何关系:)
洛根

从Swift 2.1开始,情况不再如此。现在,除了特殊init方法外,函数和方法共享与参数标签完全相同的语义。看到这个答案
ravron

11

这仅仅是Objective-C语言的影响。调用方法时,不需要显式标记方法的第一个参数(如在Objective-C中,实际上是通过方法名称“标记”)。但是,以下所有参数确实需要一个名称来标识它们。它们也可以使用(可选)本地名称以在方法本身内部使用(请参见上面注释中的Jiaaro的链接)。


2
我感觉不是说“不需要显式标记”,而是说“不能标记”,因为在那里添加标签将导致编译错误。
sivabudh 2014年

2

Swift 3.0更新:

在swift 3.0中,要求每个输入具有一个参数名称的方法必须将该参数名称作为函数调用的一部分。因此,如果您定义这样的功能

func say(name:String, msg:String) {
    print("\(name) say \(msg)")
}

您的函数调用必须是这样的

self.say(name: "Henry",msg: "Hi,Swift")

如果您想拥有像英语一样的可读功能标签,但又不想更改输入参数名称,则可以在参数名称之前添加标签,如下所示

func say(somethingBy name:String, whoIsActuallySaying msg:String) {
    print("\(name) say \(msg)")
}

然后这样称呼它

self.say(somethingBy: "Henry",whoIsActuallySaying: "Hi,Swift")

2

简单:

错误的调用函数语法(在c / c ++ / java / c#中不相同)

不正确:

say("Henry")

正确:

say(name:"Henry")

PS:你必须永远!在值之前添加“名称功能参数”。


不是2015年。那个早期的Swift版本省略了第一个标签,就像在Objective-C中的方法和函数一样,不需要任何人。您正在谈论的是比OP更新的Swift版本。
Binarian '18

@iMalleus yeah)
Fortran

1

这是编译器中的一个怪癖。就命名参数而言,函数(不是类的成员)和类方法具有不同的默认行为。这与Objective-C中命名参数的行为是一致的(但对于没有Objective-C经验的新手来说是没有意义的)。

这是语言参考中关于函数的命名参数的说法(特别是没有给出参数外部名称且参数没有默认值的参数)

但是,这些参数名称仅在函数本身的主体内使用,而在调用函数时不能使用。这些类型的参数名称称为局部参数名称,因为它们仅可在函数体内使用。

有关类方法的信息,请参见Logan的答案。


实际上不是那么简单。如果您进一步阅读文档,有时内部名称会自动转换为外部名称,据我所知,它主要是在类定义中,默认情况下需要使用2nd和以下标记。
David Berry

4
@David Agreed,我的回答涵盖了func实际上是函数的情况。Logan的答案涵盖了func实际上是方法的情况。就我个人而言,我不喜欢苹果公司的这种设计选择。无论上下文如何,函数/方法调用语法都应保持一致。程序员可以根据#语法来强制使用参数名称。
user3386109 2014年

-1

请在3+以上版本中找到用于理解的小代码。

func sumInt(a:Int,b:Int){
    print(a+b) // Displays 3 here
}

sumInt(a: 1, b: 2) // not like in other languages
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.