defer es una construcción especial de Swift que permite ejecutar un bloque específico de código justo antes de salir del ámbito (scope) de una función, independientemente de si salimos por un return normal o por un error (throw). Defer es útil para liberar recursos, deshacer cambios o finalizar operaciones.
Características del funcionamiento:
Ejemplo:
func testDefer() { print("begin") defer { print("first defer") } defer { print("second defer") } print("end") } // Imprimirá: // begin // end // second defer // first defer
Casos límite:
¿Se ejecutarán todos los bloques defer en la función si se llama fatalError dentro de ella?
Respuesta: No, si en la función se llama a fatalError (o errores no controlados similares), todos los bloques defer no se ejecutan. defer no garantiza la ejecución de código en casos de finalización abrupta de la aplicación.
Ejemplo:
func foo() { defer { print("Defer 1") } fatalError("Oops") defer { print("Defer 2") } } foo() // no imprimirá nada, resultará en un crash
Historia
En el proyecto se utilizó defer para cerrar el descriptor de archivo. Al aparecer un error, se usó fatalError en lugar de un throw correcto, lo que llevó a una fuga de recurso abierto, ya que defer no se ejecutó en caso de crash.
Historia
En una función había varios defer, algunos de los cuales dependían del estado de las variables locales. El desarrollador esperaba que la variable tuviera un valor específico, pero este valor en defer fue modificado por otro fragmento de código, y al ejecutar defer se utilizó el valor actual, y no el antiguo, lo que llevó a un error en la cancelación de la transacción por el ID incorrecto.
Historia
Dentro de un closure, se escribió un bloque defer, pensando que se ejecutaría al salir de la función externa. Como resultado, este defer se ejecutó al salir del closure, y no de toda la función, y el recurso se liberó demasiado pronto.