In Swift 1.2 gibt es ein neues Attribut mit Schließparametern in Funktionen, und wie in der Dokumentation angegeben:
Dies zeigt an, dass der Parameter immer nur aufgerufen wird (oder in einem Aufruf als @ noescape-Parameter übergeben wird), was bedeutet, dass er die Lebensdauer des Aufrufs nicht überleben kann.
Nach meinem Verständnis könnten wir vorher verwenden, [weak self]
um nicht zuzulassen, dass der Abschluss einen starken Bezug zu z. B. seiner Klasse hat, und self könnte null oder der Fall sein, in dem der Abschluss ausgeführt wird, aber jetzt @noescape
bedeutet dies, dass der Abschluss niemals ausgeführt wird wenn die Klasse deinitalisiert ist. Verstehe ich es richtig
Und wenn ich richtig @noescape
liege , warum sollte ich dann einen Verschluss verwenden, der eine reguläre Funktion enthält, wenn sie sich sehr ähnlich verhalten?
quelle
@noescape
garantiert, dass der Verschluss nicht ... asynchron verwendet wird". Das heißt, Sie können es nicht mit Netzwerkcode verwenden, der asynchron ausgelöst wird.Eine Möglichkeit, darüber nachzudenken, besteht darin, dass JEDE Variable innerhalb des @ noescape-Blocks nicht stark sein muss (nicht nur das Selbst).
Es sind auch Optimierungen möglich, da eine einmal zugewiesene Variable, die dann in einen Block eingeschlossen wird, nicht einfach am Ende der Funktion freigegeben werden kann. Es muss also auf dem Heap zugewiesen werden und mit ARC dekonstruiert werden. In Objective-C müssen Sie das Schlüsselwort "__block" verwenden, um sicherzustellen, dass die Variable blockfreundlich erstellt wird. Swift erkennt dies automatisch, sodass das Schlüsselwort nicht benötigt wird, die Kosten jedoch gleich sind.
Wenn die Variablen an einen @ nosecape-Block übergeben werden, können sie Stapelvariablen sein und benötigen keine ARC, um die Zuordnung aufzuheben.
Die Variablen müssen jetzt nicht einmal schwache Variablen sein, die auf Null verweisen (die teurer sind als unsichere Zeiger), da sie während der gesamten Lebensdauer des Blocks garantiert "lebendig" sind.
All dies führt zu einem schnelleren und optimaleren Code. Und reduziert den Aufwand für die Verwendung von @ autoclosure-Blöcken (die sehr nützlich sind).
quelle
(In Bezug auf die Antwort von Michael Gray oben.)
Ich bin mir nicht sicher, ob dies speziell für Swift dokumentiert ist oder ob sogar der Swift-Compiler es voll ausnutzt. Es ist jedoch Standard-Compiler-Design, Speicher für eine Instanz auf dem Stapel zuzuweisen, wenn der Compiler weiß, dass die aufgerufene Funktion nicht versucht, einen Zeiger auf diese Instanz im Heap zu speichern, und einen Kompilierungsfehler ausgibt, wenn die Funktion dies versucht .
Dies ist besonders nützlich, wenn nicht skalare Werttypen (wie Aufzählungen, Strukturen, Abschlüsse) übergeben werden, da das Kopieren möglicherweise viel teurer ist als das einfache Übergeben eines Zeigers an den Stapel. Das Zuweisen der Instanz ist auch erheblich kostengünstiger (eine Anweisung im Vergleich zum Aufrufen von malloc ()). Es ist also ein doppelter Gewinn, wenn der Compiler diese Optimierung vornehmen kann.
Auch hier muss das Swift-Team angeben, ob eine bestimmte Version des Swift-Compilers tatsächlich funktioniert oder nicht, oder Sie müssen den Quellcode lesen, wenn sie ihn als Open-Source-Version bereitstellen. Aus dem obigen Zitat über "geringfügige Optimierung" geht hervor, dass dies entweder nicht der Fall ist oder dass das Swift-Team dies als "geringfügig" ansieht. Ich würde es als signifikante Optimierung betrachten.
Vermutlich ist das Attribut vorhanden, damit der Compiler (zumindest in Zukunft) diese Optimierung durchführen kann.
quelle