Wie führe ich code nur einmal in Swift?
Die Antworten, die ich bisher gesehen habe (Eins, Zwei, Drei) empfehlen die Verwendung von GCD ' s dispatch_once
so:
var token: dispatch_once_t = 0
func test() {
dispatch_once(&token) {
print("This is printed only on the first call to test()")
}
print("This is printed for each call to test()")
}
test()
Ausgabe:
This is printed only on the first call to test()
This is printed for each call to test()
Aber warten Sie eine minute. token
ist eine variable, so konnte ich dies ganz einfach:
var token: dispatch_once_t = 0
func test() {
dispatch_once(&token) {
print("This is printed only on the first call to test()")
}
print("This is printed for each call to test()")
}
test()
token = 0
test()
Ausgabe:
This is printed only on the first call to test()
This is printed for each call to test()
This is printed only on the first call to test()
This is printed for each call to test()
So dispatch_once
ist von keinerlei nutzen, wenn wir ich kann, ändern Sie den Wert von token
! Und drehen token
in eine Konstante ist nicht einfach, da muss der Typ UnsafeMutablePointer<dispatch_once_t>
.
Sollen wir also aufgeben dispatch_once
im Swift? Gibt es eine sicherere Möglichkeit zum ausführen von code nur einmal?
Objective-C hat das gleiche problem. Die Idee ist, die
na dann
stackoverflow.com/q/25354882/2792531
Eric, eine Frage über die Verwendung eines gewöhnlichen bool versus
Der neueste Antworten (wie in deinen Referenzen #1 und #3) führen Sie nicht empfehlen GCD aber eine statische Klasseneigenschaft (die ist faul initialisiert werden, die in einer thread-sicheren Art und Weise).
token
im gleichen Bereich wie die dispatch_once
block, und geben Sie ihm einen besseren Namen wie onceToken
und legen Sie es RECHTS oben die dispatch_once
block selbst, so dass es sehr klar).na dann
dispatch_once
ist nicht sicherer als mit einem normalen boolean-variable.stackoverflow.com/q/25354882/2792531
Eric, eine Frage über die Verwendung eines gewöhnlichen bool versus
dispatch_once
wäre wahrscheinlich ein sehr besser, die Diskussion für Stack-Überlauf. Ich würde ganz gerne sehen, dass die Antwort (wenn es nicht schon gefragt worden, & hier beantwortet).Der neueste Antworten (wie in deinen Referenzen #1 und #3) führen Sie nicht empfehlen GCD aber eine statische Klasseneigenschaft (die ist faul initialisiert werden, die in einer thread-sicheren Art und Weise).
InformationsquelleAutor Eric | 2015-12-10
Du musst angemeldet sein, um einen Kommentar abzugeben.
Statische Eigenschaften initialisiert durch eine Schließung ausgeführt werden träge und höchstens einmal, so dass diese Abzüge nur einmal, trotz zweimal angerufen:
Beispiel läuft:
Sie nicht brauchen, um wickeln Sie eine statische Eigenschaft in einem Typ. Sie können deklarieren Sie eine Globale variable oder eine Konstante, und initialisieren Sie es mit einem Verschluss. Die closure aufgerufen werden, die träge einmal. Die Ausnahme ist, dass, wenn die Globale variable/Konstante ist definiert in main.swift, es wird noch einmal ausgeführt werden, sondern in der Reihenfolge der definition (also nicht verzögert).
Als ein beiseite, das ist eigentlich mit 'dispatch_once' in den generierten code ein :). Es ist nur versteckt in der Sprache, die Semantik.
Es nutzt
dispatch_once
auf OS X undpthread_once
unter Linux. Der Vorteil drückt es in der Sprache ist, dass es verhindert, dass jemand Zugriff auf und messing mit dem token tracking-Ausführung-Zustand, die OP war das problem.Ich hasse es zu sehen, dies geschieht über eine Eigenschaft und Methode nicht
Once.run()
InformationsquelleAutor Jeremy W. Sherman
Ein Mann ging zum Arzt und sagte: "Doktor, es tut weh, wenn ich den Stempel auf meinem Fuß". Der Arzt antwortete, "Also Hör auf, es zu tun".
Wenn Sie bewusst verändern Ihre dispatch-token, dann ja - Sie werden in der Lage sein, um den code auszuführen zweimal. Aber wenn Sie arbeiten, um der Logik entworfen, um zu verhindern, dass die mehrfache Ausführung in alle Weg, Sie werden in der Lage sein, es zu tun.
dispatch_once
ist immer noch die beste Methode, um sicherzustellen, code nur einmal ausgeführt wird, wie es behandelt alle (sehr) komplexen Ausnahmefällen, um die Initialisierung und race-conditions, die eine einfache Boolesche nicht decken.Wenn Sie besorgt sind, dass jemand versehentlich einen reset der token, können Sie wickeln Sie es in eine Methode und machen es so offensichtlich, wie es sein kann, was die Folgen sind. Etwas wie der folgende Umfang der token an die Methode, und verhindern, dass jedermann ändern es ohne ernsthafte Anstrengung:
LOL. Beste Erklärung .
Ich im Grunde nicht einverstanden sind. Die Dokumentation für
dispatch_once
besagt, dass es "Führt eine block-Objekt nur einmal für die Lebensdauer einer Anwendung." Keine Ambiguität, die API zu brechen den Vertrag. Und dass der Arzt inkompetent ist.Haben Sie einen Blick auf diese Antwort von Greg Parker (von Apple) stackoverflow.com/a/19845164/1187415: "Die Umsetzung der dispatch_once() erfordert, dass die dispatch_once_t null ist, und nie nicht null ist. ..."
Greg fügt hinzu: "Instanzvariablen werden initialisiert auf null, aber Ihre Speicher vorher gespeichert einen anderen Wert. Das macht Sie unsicher für dispatch_once() verwenden." Genug gesagt...
InformationsquelleAutor Adam Wright
Ich denke, der beste Ansatz ist, um sich nur konstruieren, Ressourcen träge, wie gebraucht. Swift macht dies einfach.
Gibt es mehrere Möglichkeiten. Wie bereits erwähnt, können Sie initialisieren einer statischen Eigenschaft innerhalb eines Typs mit einem Verschluss.
Jedoch die einfachste option ist, um eine Globale variable (oder Konstante), und initialisieren Sie es mit einer Schließung dann darauf verweisen, dass die variable überall dort, wo der code für die Initialisierung erforderlich ist, um einmal passiert:
Weitere option ist, um wickeln Sie die Art innerhalb einer Funktion, so dass es liest sich besser, wenn Sie anrufen. Zum Beispiel:
Können Sie tun, Varianten dieser, wie gebraucht. Zum Beispiel, statt der Verwendung der Typ-interne Funktion, die Sie verwenden können, eine private Globale und interne oder öffentliche Funktion, wie gebraucht.
Aber ich denke, der beste Ansatz ist einfach, zu bestimmen, welche Ressourcen Sie brauchen, um zu initialisieren und erstellen Sie träge als Globale oder statische Eigenschaften.
InformationsquelleAutor Tom Pelaia