Xcode 8: Funktionstypen dürfen keine Argumentbezeichnung haben, die meinen Build beschädigt

74

Es scheint, dass Swift aus irgendeinem Grund beschlossen hat, die Codierung darin weniger lesbar zu machen, indem Benutzer gezwungen werden, die Parameterbezeichnungen für den Abschluss-Handler zu entfernen. Ich habe die Swift-Diskussion gelesen und denke immer noch, dass es ein Fehler ist. Zumindest hätten sie es optional machen können.

Gibt es beim Erstellen mit Xcode 8 eine Möglichkeit, den Compiler zur Verwendung von Swift 2.3 zu zwingen, damit ich diese Fehler nicht mehr erhalte? Ich habe die Option zur Verwendung von Legacy-Swift (unter Build-Einstellungen) aktualisiert, Legacy-Unterstützung in xcode aber es scheint immer noch, dass folgende Fehlermeldung angezeigt wird:

Funktionstypen dürfen keine Argumentbezeichnung 'isloggedIn' haben. Verwenden Sie stattdessen '_'

Fehler Xcode 8

Wie kann ich meine Etiketten in meinen Fertigstellungshandlern behalten?

UKDataGeek
quelle
Es sieht so aus, als würde nur gesagt, dass Sie den Parameter 'error' nicht haben können, nicht, dass Sie ihm keinen Namen geben können. Haben Sie versucht, "Fehler" in etwas anderes umzubenennen?
Dudeman
22
@dudeman Swift 3 verbietet ausdrücklich die Verwendung von Argumentbezeichnungen in Funktionstypen. Fragwürdige Wahl, sehr frustrierend.
Crashalot
17
Frustrierend und nervig. Ich rippe guten Code heraus, um ihn weniger lesbar und fehleranfällig zu machen
UKDataGeek
13
Ich hasse diese Veränderung absolut.
UKDataGeek
5
Es scheint, als würde Swift 3 versuchen, zu philosophisch einwandfrei zu sein, und die Menschheitsgeschichte sagt uns, dass dies nicht der effizienteste Weg ist, um Dinge zu erledigen. Hassen Sie absolut viele der Änderungen in Swift 3
funct7

Antworten:

98

Die Swift-Designer haben beschlossen, Argumentbezeichnungen für Funktionstypen zu verbieten.

Die Argumentation wird hier erklärt: https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md

Dies ist eine frustrierende und fragwürdige Entscheidung, da das Verbot von Argumentbezeichnungen das falsche Aufrufen von Schließungen erheblich erleichtert, was wichtiger erscheint als die Vereinfachung des Typensystems der Sprache.

Benutzerfreundlichkeit> Ideologie.

Crashalot
quelle
6
Ich stimme dem zu - aber es ist nicht wirklich eine Lösung. Ich werde vorschlagen, dass wir daran arbeiten, einen Vorschlag einzureichen, um dies möglicherweise optional zu machen.
UKDataGeek
Habe dies als die aktuelle Lösung hinzugefügt, wie es wirklich gut erklärt ist
UKDataGeek
16
Immer noch keine Anzeichen für die Lösung, die ich in Swift 3.1 vorgeschlagen habe - wir hoffen, dass wir sie vor Swift 4 bekommen. Hassen Sie diese Änderung so sehr!
UKDataGeek
@Crashalot Aber wie kann man Argumente durch diese Funktionen weiterleiten lassen?!
MatterGoal
@matterGoal was meinst du?
UKDataGeek
23

Eine zu berücksichtigende Problemumgehung. Sie können nicht tun:

func doStuff(completion: (foo: Int, bar: String) -> Void) {
    ...
    completion(foo: 0, bar: "")
}

... aber du kannst:

func doStuff(completion: ((foo: Int, bar: String)) -> Void) {
    ...
    completion((foo: 0, bar: ""))
}

Das heißt, Sie haben ein einziges unbenanntes Argument für Ihre Schließung, das in diesem Fall ein Tupel ist (foo: Int, bar: String).

Es ist auf seine Weise hässlich, aber zumindest behalten Sie die Argumentbezeichnungen bei.

sam-w
quelle
1
Jede Idee, wie dies mit typealias public typealias funktioniert ImageDataCompletion = (((imgData imgData: Data?, _ err: MYGR8TErrorClass?)) -> Void) gibt: ... Tuple-Element kann nicht zwei Beschriftungen haben !!!! wtf ????
Anton Tropashko
@ AntonTropashko: (((imgData imgData: Data?, _ err: MYGR8TErrorClass?)) -> Void)sollte sein (((imgData: Data?, err: MYGR8TErrorClass?)) -> Void). Sie versuchen, Ihre Tupelelemente zweimal zu beschriften
sam-w
2
Eine Einschränkung dieser Lösung besteht darin, dass Tupel keinen einzigen Wert haben können.
Mark
11

Basierend auf den obigen Informationen scheint es, dass die einzige Möglichkeit, dies wirklich zu beheben und sicherzustellen, dass sein Leistungsträger darin besteht, einen Vorschlag zu unterbreiten, Argumentbeschriftungen optional zu machen, um:

  1. Verbesserung der Entwicklungsgeschwindigkeit (ohne Argumentbezeichnungen müssen wir jedes Mal, wenn wir den Completion-Handler eingeben, nach oben scrollen.
  2. Fehler reduzieren: (Ich habe bereits mehrere Fehler aufgrund falscher Einträge für den Abschluss-Handler verursacht, insbesondere bei solchen, die boolesche Werte erwarten.)
  3. Machen Sie den Code für alle Teammitglieder lesbarer. Nicht jeder hat nur ein Teammitglied und daher ist es ein Muss, den Code anderer Leute leicht abrufen zu können.
  4. Schließlich bedeutet gute Programmierpraxis, dass die Lösung genauso aussehen sollte wie das tatsächlich entwickelte Element. completionhandler: (newvalues, nil)sieht weniger aus wie das verwaltete Element alscompletionhandler(results: newValue, error:nil)

Ich würde es lieben, wenn Leute, die dies lesen, ihr Feedback / ihre Kommentare dazu weiter unten teilen, bevor ich es abschicke, damit ich zeigen kann, dass es andere gibt, die dies unterstützen.

Bearbeiten: Ich habe den Pitch hier eingereicht: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161010/028083.html, der anscheinend vereinbart wurde. Es sieht so aus, als würde es passieren, aber es wird diskutiert, ob dies als Swift 4-Verbesserung eingereicht wird (sehr wahrscheinlich).

UKDataGeek
quelle
2
Okay, da Sie danach gefragt haben, lassen Sie mich entlüften: Es wird nicht das erste Mal sein, dass OpenSource-Affen etwas vermasselt haben (verwendbar vor ihrem wertvollen Beitrag). Amen.
Anton Tropashko
@AntonTropashko Upvote für die Entlüftung bei Stapelüberlauf - hoffe, Sie fühlen sich besser?
UKDataGeek
hat die Antwort auch positiv bewertet! was für eine Erleichterung! Ernsthaft: Nein
Anton Tropashko
@ MobileBloke Wie ist der Status davon? Ich sehe nicht, dass es in der Sprache kam ...
Frangulyan
Nein - sieht so aus, als wäre es depriorisiert worden. Es ist immer noch so nervig.
UKDataGeek
9

Sie müssen _ verwenden, um Ihre Parameter unbenannt zu machen, und das ist bedauerlich. Anstatt _ an jeden Parameter anzuheften und dann blind Ihre Funktion aufzurufen, würde ich vorschlagen, ein Wrapper-Objekt zu erstellen.

Da der Verlust benannter Parameter für Funktionstypen ein höheres Risiko birgt, dass Sie die Funktion mit den falschen Werten aufrufen, würde ich empfehlen, die Parameter in eine Struktur zu packen und dies als einzigen Parameter für Ihre Funktion zu verwenden.

Auf diese Weise werden die Felder Ihrer Struktur benannt, und es gibt nur einen Werttyp, der an Ihre Funktion übergeben werden kann. Es ist umständlicher, als wenn wir die Parameter der Funktion benennen könnten, aber wir können nicht. Zumindest auf diese Weise sind Sie sicherer und fühlen sich weniger schmutzig.

struct LineNoteCellState {

    var lineNoteText: String?
    var printOnInvoice = false
    var printOnLabel = false
}

Hier ist ein Beispiel dafür:

cell.configure(editCallback: { (_ state: LineNoteCellState) in

    self.lineNoteText = state.lineNoteText
    self.printOnInvoice = state.printOnInvoice
    self.printOnLabel = state.printOnLabel
})
Michael Peterson
quelle
4

Semi-Workaround, beachten Sie das _

completion: (_ success: Bool) -> Void
Maciej Swic
quelle
1
Dies scheint für mich nicht automatisch zu vervollständigen - Was ist die Funktion des Unterstrichs vor dem Erfolgsparameter?
UKDataGeek