ProgrammingSwift Developer

What is 'defer' in Swift? How does it work and what is it used for, what are the non-standard scenarios of its use?

Pass interviews with Hintsage AI assistant

Answer.

The defer statement postpones the execution of code until the current scope is exited, usually from a function. It is useful for resource cleanup, closing files, and freeing memory — so-called automated cleanup.

Features:

  • Defer blocks are executed in reverse order of their declaration (LIFO).
  • The call always occurs — both on a normal function exit and when throwing an error.
  • It helps avoid duplication of cleanup code and supports a clean function architecture.

Example:

func processFile() { let file = openFile() defer { closeFile(file) } // Working with the file // file will be closed even in case of throw or return }

Unconventional use: partial imitation of constructs like 'finally', grouping code for logging and monitoring execution times.

Trick question.

Will defer execute if the application terminates during the execution of the function?

— No. Defer executes only on normal exit from the scope (return, throw or normal exit). If the application crashes (e.g., due to a SIGKILL signal or fatalError), the defer blocks will not be executed.

Example:

func foo() { defer { print("Clean up") } fatalError("Crash!") // defer will not execute }

Examples of real errors due to ignorance of the topic's nuances.


Story

A function working with sockets did not clean up the connection in case of throw. Data remained hanging, connections were not released. After introducing defer, everything worked correctly: resources were always closed.


Story

A developer tried to rely on defer for releasing global state. When a fatalError occurred, the resource was not released, leading to service hangs and the need for a restart.


Story

In a function, several defer statements were declared, assuming they would execute in the order of declaration. As a result, resources were closed in the wrong order (for example, a file descriptor was closed first, and then access was attempted to it). Solution: remember the LIFO order of defer block execution.