defer is a special Swift construct that allows executing a certain block of code right before exiting the scope of a function, regardless of whether we exited it through a regular return or due to an error (throw). Defer is convenient for resource cleanup, undoing changes, or finalizing operations.
Working features:
Example:
func testDefer() { print("begin") defer { print("first defer") } defer { print("second defer") } print("end") } // Output: // begin // end // second defer // first defer
Edge cases:
Will all defer blocks in a function execute if fatalError is called within it?
Answer: No, if a function calls fatalError (or similar uncontrolled crashes), all deferred blocks will not execute. defer does not guarantee code execution in cases of abnormal application termination.
Example:
func foo() { defer { print("Defer 1") } fatalError("Oops") defer { print("Defer 2") } } foo() // outputs nothing, crash will occur
Story
In a project, defer was used to close a file descriptor. When an error occurred, fatalError was used instead of a proper throw, leading to a leak of the open resource since defer did not run during the crash.
Story
In one function, there were several defer statements, some of which depended on the state of local variables. The developer expected a variable to equal a specific value, but this value changed in defer due to another part of the code, and when defer executed, it used the current value rather than the old value, leading to a transaction rollback bug for the wrong ID.
Story
In a nested closure, a defer block was written, thinking it would execute when exiting the outer function. As a result, this defer executed upon exiting the closure, not the entire function, and the resource was released too early.