Frage Aktualisierung der Schließungen von Swift 3 - @escaping


Ich habe meinen Code auf Xcode 8.0 Beta 6 aktualisiert, aber ich blieb bei dem, was über die neue nicht-flüchtige Schließung zu sein scheint. Im folgenden Code schlägt Xcode vor, hinzuzufügen @escaping vor completion: in der ersten Zeile des folgenden Codes, aber das wird immer noch nicht kompilieren und geht in Kreisen. *

(BEARBEITEN: In der Tat sollte @escaping hinzugefügt werden nach  completion:, wie Xcode es vorschlägt. Die Warnung wird möglicherweise weiterhin angezeigt, aber durch das Bereinigen und Kompilieren wird sie entfernt.) * Wie sollte dieser Code neu geschrieben / repariert werden, damit er im aktualisierten Swift 3 funktioniert? Ich habe mir das neue Handbuch angesehen, konnte aber keine geeigneten Codebeispiele finden.

func doSomething(withParameter parameter: Int, completion: () -> ()) {
    // Does something

    callSomeOtherFunc(withCompletion: completion)
  }

// Calling the method and execute closure 
doSomething(withParameter: 2) {
  // do things in closure
}

Jede Hilfe sehr geschätzt!


75
2017-08-21 11:06


Ursprung


Antworten:


Swift 3: Verschlussparameterattribute werden nun auf den Parameter angewendet Artund nicht der Parameter selbst

Vor Swift 3, die Schließung Attribute @autoclosure und @noescape waren Attribute zum Verschluss Parameter, aber sind jetzt Attribute für den Parameter Art; Siehe folgenden akzeptierten Swift-evolution-Vorschlag:

Ihre spezifische Frage bezieht sich auf das Attribut des Parametertyps @escaping (für die die gleiche neue Regel zutrifft), wie im angenommenen Swift-evolution-Vorschlag beschrieben, um Verschlussparameter standardmäßig nicht zu umgehen:

Diese Vorschläge werden nun beide in der Beta - Phase von Xcode 8 implementiert (siehe Versionshinweise für Xcode 8 beta 6; Entwickler Konto-Login für den Zugriff benötigt)

Neu in Xcode 8 Beta 6 - Swift Compiler: Schnelle Sprache

Closure-Parameter werden standardmäßig nicht und nicht explizit geschlossen   mit kommentiert werden @noescape. Benutzen @escaping um anzuzeigen, dass a   Schließungsparameter kann entkommen. @autoclosure(escaping) wird jetzt geschrieben als    @autoclosure @escaping. Die Anmerkungen @noescape und    @autoclosure(escaping) sind veraltet. (SE-0103)

...

Neu in Xcode 8 beta - Swift und Apple LLVM Compiler: Swift Language

Das @noescape und @autoclosure Attribute müssen jetzt geschrieben werden   vor dem Parametertyp statt vor dem Parameternamen. [SE-0049]

Daher verwenden Sie den Nicht-Standard @escaping Attribut wie folgt; angewendet auf die Art der Schließung Parameter, anstatt den Parameter selbst

func doSomething(withParameter parameter: Int, completion: @escaping () -> ()) {
    // ...
}

(Einschließlich meiner Antwort auf eine Frage in einem untenstehenden Kommentar, da Kommentare keine persistenten Daten zu SO sind)

@Cristi Băluţă: "Was bedeutet Flucht? Nie diese Schlüsselwörter gesehen   vor swift3 Auto-Konvertierung ... "

Siehe z.B. der Link zum SE-0103 Evolution Vorschlag oben (wie auch der zitierte Text aus den Beta-6-Release-Notes): Bisher waren Verschlussparameter standardmäßig nicht vorhanden (daher ist für das Escaping keine explizite Annotation erforderlich), sie werden jetzt jedoch standardmäßig nicht mehr entfernt. Daher die Zugabe von @escaping explizit annotieren, dass ein Closure-Parameter (im Gegensatz zu seinem Standardverhalten) ausgelöst werden kann. Dies erklärt auch warum @noescapeist jetzt veraltet (keine Notwendigkeit, das Standardverhalten zu kommentieren).

Um zu erklären, was es bedeutet, dass ein Verschlussparameter verloren geht, zitiere ich die Sprachreferenz - Attribute:

"Wenden Sie dieses Attribut auf den Typ eines Parameters in einer Methode oder Funktionsdeklaration an, um anzugeben, dass der Wert des Parameters gespeichert werden kann   spätere Ausführung. Dies bedeutet, dass der Wert den Wert überschreiten darf   Lebenszeit des Anrufs. "


58
2017-08-21 12:05



@noescape

Von xcode 8 beta 6 @noescape ist der Standardwert. Zuvor @escaping war der Standard. Jeder, der von früheren Versionen auf "swift 3.0" aktualisiert wird, sieht sich möglicherweise diesem Fehler gegenüber.

Sie können keine speichern @noescape Schließung innerhalb einer Variablen. Wenn Sie eine Schließung in einer Variablen speichern können, können Sie die Schließung von überall in Ihrem Code ausführen. Aber @noescape gibt an, dass der closure-Parameter nicht den Rumpf der Funktion verlassen kann.

Dies wird Compiler Fehler in Xcode 8 geben

class MyClass {

    var myClosure: (() -> ())?

    func doSomething(finishBlock: () -> ()) {
        myClosure = finishBlock    // ️ Error: Assigning non-escaping parameter 'finishBlock' to an @escaping closure
    }
}

Dies wird ok kompilieren (explizit schreiben @escaping)

class MyClass {

    var myClosure: (() -> ())?

    func doSomething(finishBlock: @escaping () -> ()) {
        myClosure = finishBlock
    }
}

Vorteile von @noescape:

  • Der Compiler kann Ihren Code für eine bessere Leistung optimieren
  • Der Compiler kann sich um die Speicherverwaltung kümmern
  • Es besteht keine Notwendigkeit, einen schwachen Verweis auf das Selbst im Verschluss zu verwenden


Für Details besuchen Sie bitte: Machen Sie nicht-flüchtige Schließungen zum Standard


22
2017-10-24 10:28