Swift: Fehlende Argumentbezeichnung 'xxx' im Aufruf

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

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

Ich muss verwenden

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

Warum ? Wenn ich mehr als zwei Variablen in func eingefügt habe, damit ich beim Aufrufen dieser Funktion var-Namen anstelle der ersten Variable schreiben muss, ist
das wirklich problematisch, und ich sehe keine Erklärung im iBook Swift-Tutorial.

henry4343
quelle
2
Ihr Funktionsname ist "say", aber Sie rufen sayHello auf?
Sam B
1
möglicherweise verwandt: stackoverflow.com/questions/24049272/…
Jiaaro
Ich habe diese Frage gesehen, aber sie hat mein Problem nicht gelöst
henry4343
Ist das eine Methode? (Eine Funktion im Rahmen einer Klasse?)
Logan

Antworten:

70

Ein möglicher Grund ist, dass es sich tatsächlich um eine Methode handelt. Methoden sind sehr hinterhältig, sie sehen genauso aus wie normale Funktionen, aber sie verhalten sich nicht gleich. Schauen wir uns das an:

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)

Hier ist der lustige Teil: Deklarieren Sie eine Funktion innerhalb einer Klasse und es ist keine Funktion mehr ... es ist eine Methode

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

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

Dies ist Teil des Verhaltensentwurfs für Methoden

Apple Docs:

Insbesondere gibt Swift dem ersten Parameternamen in einer Methode standardmäßig einen lokalen Parameternamen und dem zweiten und den nachfolgenden Parameternamen standardmäßig sowohl lokale als auch externe Parameternamen. Diese Konvention entspricht der typischen Namens- und Aufrufkonvention, mit der Sie beim Schreiben von Objective-C-Methoden vertraut sind, und ermöglicht ausdrucksstarke Methodenaufrufe, ohne dass Sie Ihre Parameternamen qualifizieren müssen.

Beachten Sie die automatische Vervollständigung: Geben Sie hier die Bildbeschreibung ein

Logan
quelle
Komisch, wie ohne Angabe des Namens für den zweiten Parameter in Playground wunderbar zu funktionieren scheint!
user1107173
1
@ user1107173 - Das liegt daran, dass es außerhalb des Kontexts einer Klasse liegt. Wenn Sie es in eine Klasse einfügen, wird der Name für den zweiten Parameter angegeben. Spielplatz hat nichts damit zu tun :)
Logan
Dies gilt ab Swift 2.1 nicht mehr. Funktionen und Methoden haben jetzt mit Ausnahme spezieller initMethoden genau dieselbe Semantik für Parameterbezeichnungen . Siehe diese Antwort .
Ravron
11

Dies ist einfach ein Einfluss der Objective-C-Sprache. Beim Aufrufen einer Methode muss der erste Parameter einer Methode nicht explizit gekennzeichnet werden (wie in Objective-C wird er effektiv mit dem Namen der Methode "gekennzeichnet"). Alle folgenden Parameter benötigen jedoch einen Namen, um sie zu identifizieren. Sie können auch einen (optionalen) lokalen Namen zur Verwendung innerhalb der Methode selbst verwenden (siehe Jiaaros Link in den obigen Kommentaren).

Ephemera
quelle
2
Ich habe das Gefühl, anstatt zu sagen "muss nicht explizit beschriftet werden", könnten wir sagen "kann nicht beschriftet werden", da das Hinzufügen eines Etiketts dort zu einem Kompilierungsfehler führt.
Sivabudh
2

Swift 3.0 Update:

In Swift 3.0 müssen Methoden mit einem Parameternamen pro Eingabe diesen Parameternamen als Teil des Funktionsaufrufs haben. Also, wenn Sie die Funktion so definieren

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

Ihr Funktionsaufruf muss so sein

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

Wenn Sie Englisch wie lesbare Funktionsbezeichnungen haben möchten, aber den Namen der Eingabeparameter nicht ändern möchten, können Sie die Bezeichnung wie folgt vor den Parameternamen einfügen

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

Dann nenne ich es so

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

Einfach:

Syntax für falsche Aufruffunktionen (in c / c ++ / java / c # nicht identisch)

Falsch:

say("Henry")

Richtig:

say(name:"Henry")

PS: Das musst du immer ! Fügen Sie vor dem Wert " name function parameter " hinzu.

Fortran
quelle
Nicht 2015. In dieser frühen Swift-Version wurde das erste Label weggelassen, genau wie in Objective-C in Methoden und Funktionen brauchte niemand. Sie sprechen von einer neueren Swift-Version als OP.
Binarian
@iMalleus yeah)
Fortran
1

Dies ist eine Eigenart im Compiler. Funktionen (die nicht Mitglieder einer Klasse sind) und Klassenmethoden haben ein unterschiedliches Standardverhalten in Bezug auf benannte Parameter. Dies steht im Einklang mit dem Verhalten benannter Parameter in Ziel-C (macht jedoch keinen Sinn für jemanden, der neu ist und keine Erfahrung mit Ziel-C hat).

Hier ist, was die Sprachreferenz über benannte Parameter für Funktionen zu sagen hat (insbesondere Parameter, bei denen kein externer Name für den Parameter angegeben ist und der Parameter keinen Standardwert hat)

Diese Parameternamen werden jedoch nur im Hauptteil der Funktion selbst verwendet und können beim Aufrufen der Funktion nicht verwendet werden. Diese Arten von Parameternamen werden als lokale Parameternamen bezeichnet, da sie nur zur Verwendung im Funktionskörper verfügbar sind.

Informationen zu Klassenmethoden finden Sie in Logans Antwort.

user3386109
quelle
Es ist eigentlich nicht so einfach. Wenn Sie weiter in die Dokumentation hineinlesen, wird der interne Name manchmal automatisch in einen externen Namen umgewandelt. Soweit ich mich erinnere, sind die zweiten und folgenden Tags standardmäßig in Klassendefinitionen erforderlich.
David Berry
4
@ David Einverstanden, meine Antwort deckt den Fall ab, in dem funcdas tatsächlich eine Funktion ist. Logans Antwort deckt den Fall ab, in dem funces sich tatsächlich um eine Methode handelt. Persönlich mag ich diese Designauswahl von Apple nicht. Die Syntax für Funktions- / Methodenaufrufe sollte unabhängig vom Kontext konsistent sein. Programmierer können die #Syntax verwenden, um die Verwendung von Parameternamen als Stilfrage zu erzwingen.
user3386109
-1

Den kleinen Code zum Verständnis finden Sie in Swift 3+.

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

sumInt(a: 1, b: 2) // not like in other languages
Lokesh G.
quelle