ProgrammierungiOS Entwickler

Beschreiben Sie den Mechanismus von defer in Swift. Worauf sollte man bei Grenzfällen und Besonderheiten achten?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

defer ist eine spezielle Swift-Konstruktion, die es ermöglicht, einen bestimmten Codeblock direkt vor dem Verlassen des Gültigkeitsbereichs (scope) der Funktion auszuführen, unabhängig davon, ob wir sie durch ein normales return oder durch einen Fehler (throw) verlassen haben. Defer lässt sich gut verwenden, um Ressourcen freizugeben, Änderungen zurückzusetzen oder Operationen abzuschließen.

Besonderheiten:

  • Wenn eine Funktion mehrere defer-Anweisungen enthält, werden sie in umgekehrter Reihenfolge ausgeführt (Last In, First Out - LIFO).
  • defer wird auch bei Auftreten eines Fehlers (throw) oder bei jedem return aus der Funktion ausgeführt.
  • In Closures gehört defer zum Funktionskörper des Closures und nicht zu dem Ort, an dem das Closure aufgerufen wird.

Beispiel:

func testDefer() { print("begin") defer { print("first defer") } defer { print("second defer") } print("end") } // Gibt aus: // begin // end // second defer // first defer

Grenzfälle:

  • defer erfasst die Werte von Variablen zum Zeitpunkt des Auftretens von defer: Wenn wir in einem defer-Closure Variablen verwenden, sind die Änderungen zum Zeitpunkt der Ausführung von defer sichtbar.
  • Wenn die Funktion mit fatalError endet, wird defer nicht aufgerufen.

Fangfrage.

Werden alle defer-Blocks in einer Funktion ausgeführt, wenn fatalError innerhalb dieser aufgerufen wird?

Antwort: Nein, wenn in der Funktion fatalError (oder ähnliche unkontrollierbare Abstürze) aufgerufen wird, werden alle durch defer verzögerten Blocks nicht ausgeführt. defer garantiert nicht, dass der Code im Falle eines unerwarteten Beendens der Anwendung aufgerufen wird.

Beispiel:

func foo() { defer { print("Defer 1") } fatalError("Oops") defer { print("Defer 2") } } foo() // gibt nichts aus, es tritt ein Crash auf

Beispiele für reale Fehler aufgrund mangelnden Wissens über die Feinheiten des Themas.


Geschichte

Im Projekt wurde defer zum Schließen des Dateihandlers verwendet. Bei Auftreten eines Fehlers wurde fatalError anstelle von korrektem throw verwendet, was zu einem Leck offener Ressourcen führte, da defer bei einem Crash nicht ausgeführt wurde.


Geschichte

In einer Funktion gab es mehrere defer-Anweisungen, von denen einige von dem Zustand lokaler Variablen abhingen. Der Entwickler erwartete, dass die Variable einen bestimmten Wert hat, aber dieser Wert änderte sich in defer durch einen anderen Codeabschnitt, und bei der Ausführung von defer wurde der aktuelle und nicht der alte Wert verwendet, was zu einem Fehler beim Abbrechen der Transaktion mit der falschen ID führte.


Geschichte

In einem verschachtelten Closure wurde ein defer-Block geschrieben, in der Annahme, dass er beim Verlassen der äußeren Funktion ausgeführt wird. Infolgedessen wurde dieser defer beim Verlassen des Closures und nicht der gesamten Funktion ausgeführt, und die Ressource wurde zu früh freigegeben.