Swift 3: Die Verwendung von Nicht-Escaping-Parametern beim Schließen kann dazu führen, dass es entweicht

8

Ich habe die folgende Funktion, wo ich Abschluss-Handler habe, aber ich bekomme diesen Fehler:

%Vor%

Hier ist mein Code:

%Vor%

Jeder von euch weiß, warum ich diesen Fehler bekomme?

Ich schätze wirklich deine Hilfe

    
user2924482 13.02.2017, 22:38
quelle

3 Antworten

8

Sieht so aus, als müssten Sie explizit definieren, dass der Closure entkommen darf.

Aus der Apple Developer-Dokumentation ,

  

Eine Closure soll eine Funktion verlassen, wenn die Closure als Argument für die Funktion übergeben wird. Sie wird jedoch aufgerufen, nachdem die Funktion zurückgegeben wurde. Wenn Sie eine Funktion deklarieren, die einen Closure als einen ihrer Parameter akzeptiert, können Sie vor dem Typ des Parameters @escaping schreiben, um anzuzeigen, dass der Closure entkommen darf.

TLDR; Fügen Sie das Schlüsselwort @escaping nach der Vervollständigungsvariablen hinzu:

%Vor%     
Mark Barrasso 13.02.2017 22:41
quelle
3

Ein "fliehender" Verschluss ist ein Verschluss, der den Umfang, in dem er erstellt wurde, überlebt. Entweichende Verschlüsse erfordern besondere Sorgfalt bei der Referenzzählung und der Speicherverwaltung und können schwieriger zu optimieren sein.

Vor Swift 3 wurde als Standard für Schließungen angenommen, dass sie fliehen würden. Dies bedeutete, dass Entwickler Schließungen, die bekanntlich nicht sind, explizit identifizieren mussten, um dem Compiler zu ermöglichen, Optimierungen vorzunehmen. Die Community fand heraus, dass der Compiler in der Tat leicht selbst herausfinden konnte, ob eine Closure auslief oder nicht, und entschied, dass ein aggressiver Ansatz zum Ausstieg zu einem schnelleren Code führen könnte. Das Ergebnis ist, dass jetzt davon ausgegangen wird, dass Closures nicht mehr ausgeführt werden, und Sie müssen Closures kennzeichnen, die mit dem Attribut @escaping entkommen.

In Ihrem Fall ist der Abschluss, den URLSession.shared.dataTask annimmt, selbst ein escaping closure. Wenn Sie also einen Abschluss darin verwenden, muss dieser auch als @escaping markiert werden.

    
zneak 13.02.2017 22:49
quelle
0

@escaping ist für alle aufrufenden Methoden infektiös, und der Compiler bestimmt, wann Sie müssen es einschließen.

Betrachten Sie dieses Beispiel (das kompiliert):

%Vor%

Dieses modifizierte Beispiel erzeugt jedoch zwei Fehler vom Typ non-escaping parameter may allow it to escape :

%Vor%

Der Versand auf main bedeutet, dass die dispatchLater -Methode @escaping benötigt, und wenn Sie das hinzugefügt haben, erfordert die dispatchSometime -Methode auch @escaping , damit das Beispiel kompiliert werden kann.

%Vor%

Allerdings ist das Mitnehmen nur:

  • Fügen Sie weiterhin @escaping der Aufrufkette hinzu, bis der Compiler aufhört, sich zu beschweren.
  • Das Schlüsselwort ändert nichts: Es ist eine Warnung, die im Wesentlichen lautet: "Achten Sie darauf, weak mit den erfassten Variablen zu verwenden, da diese zusammen mit dem Block selbst beibehalten werden können."

Implikationen

Der wirklich spaßige Fall ist, dass Sie mehrere Methoden anpassen müssen, um das @escaping Schlüsselwort einzufügen, das den Compiler dazu bringt, sich nicht mehr zu beschweren. Wenn diese Methoden jedoch tatsächlich einem Protokoll entsprechen, müssen die Methoden dieses Protokolls auch das Schlüsselwort @escaping erhalten, das auch alle anderen Protokollkonformitäten infiziert. Spaß!

    
Dan Rosenstark 14.08.2017 18:56
quelle