ProgrammingMiddle/Senior iOS Developer

What is the essence of the defer operator in Swift and what are the main scenarios for its application, features of working with closures and resource management?

Pass interviews with Hintsage AI assistant

Answer.

Background

The defer operator was introduced in Swift for safe and guaranteed cleanup of resources or execution of code in the exit block of a scope, similar to finally/using/RAII in other languages.

The Issue

Multi-step initialization, file operations, cross-scenario exits from a function — require guaranteed resource release or execution of logic (closing a file, unlocking a mutex, returning an object to a pool, resetting temporary state). Before defer, this had to be done manually in every return.

The Solution

defer guarantees the execution of its code upon exiting the current scope, regardless of whether the exit is normal or via throw. You can declare multiple defer — they will execute in reverse order of declaration.

Example of resource release:

func processFile(path: String) throws { let file = try openFile(path) defer { file.close() } // Guaranteed to be called even on errors // ... work with file ... }

Key features:

  • Executes on any exit from the scope (return, throw, break),
  • Multiple defer declarations can be made — they execute in reverse order,
  • Very useful for resource management, error handling, locking/unlocking, resetting temporary states.

Trick Questions.

Can defer capture variables by reference and how does it affect closure behavior?

Yes, defer captures all used variables at the time of invocation, according to closure capture rules (copy for value types, reference for reference types). Capturing a mutable external value variable would be an error — it may change by the time defer is executed.

How does nested defer work inside loops and functions?

If defer is declared inside a loop, it executes on every completion of the iteration scope:

for _ in 1...3 { defer { print("End of iteration") } print("Inside") }

Will output:

Inside
End of iteration
Inside
End of iteration
Inside
End of iteration

Can defer not execute?

The execution of defer code is guaranteed only if the scope is truly exited. But if the process crashes (fatalError, crash), or exit is called, defer does not execute. Additionally, defer does not work at the method level of objects — only within the function/block scope.

Typical Mistakes and Anti-Patterns

  • Using defer for asynchronous operations (the last defer releases, but the asynchronous code is not yet completed),
  • Implicitly capturing external mutable variables (race condition in multithreading),
  • Declaring many defer in a row — leading to reduced readability and debugging.

Real-life Example

Negative Case

In the code after opening a file and working with it, returns were made through different return/throw statements, forgetting to close the file in one place. As a result, open file handle leaked into the system.

Pros:

  • Simple linear logic

Cons:

  • Easy to forget to release the resource on every exit
  • Memory leak/resource leak

Positive Case

Using defer for guaranteed unlocking of the mutex, releasing the file descriptor, and resetting the progress flag:

func criticalSection() { lock() defer { unlock() } // ... work ... }

Pros:

  • High resource safety
  • Reduced number of errors

Cons:

  • Additional nested scope with many defer