La manera más rápida de darnos cuenta de que hay algo que no funciona como debería es cuando nuestra aplicación hace crash, en ese momento sabemos que algo no esta funcionando como deberia.
Bajo ese mismo concepto, una buena forma de darnos cuenta durante el desarrollo que algun valor esta fuera de rango o un valor esperado no esta ahi es haciendo crash en nuestra aplicacion voluntariamente.
assert, assertionFailure, precondition, preconditionFailure, fatalError
Estas funciones nos permite poder detener nuestra aplicacion («Crash») ayudandonos a detectar estados imposibles en nuestra aplicacion, y cuando digo estados imposibles me refiero a situaciones que no deberia suceder pero suceden, como un identificador nulo cuando tiene que estar disponible, un string vacio cuando tiene que tener valor, una variable que se mantiene nulo cuando no deberia, que no ayudaran a detectar algun error de logica o flujo en nuestro codigo.
Ahora bien, assert, assertionFailure, precondition, fatalError, todas estas funciones realizan la misma accion (Detener la ejecucion de la aplicacion), con ciertas diferencias, y es importante identificar estas diferencias.
| Disponible en Dev Builds | Disponible en Release Build | |
| assert | ✅ | ⛔ |
| assertionFailure | ✅ | ⛔ |
| precondition | ✅ | ✅ |
| preconditionFailure | ✅ | ✅ |
| fatalError | ✅ | ✅ |
Debug Builds
Durante el desarrollo, digamos al correr nuestra app con xcode o un dev builds, esta compilado con la propiedad Level Optimization con «-O0» y esto nos permite que muchas funciones de desarrollo este disponibles en nuestros builds, y ayudando a que los asserts y assertionsFailure este disponibles en nuestro codigo.
Release Builds
Lo release builds a diferencia de los debug estos tiene la propiedad Level Optimization con «-O» o –Owholemodule permitiendo un mayor grados de optimizacion, y eliminando el codigo de asserts entre otras cosas.

Dado estos es muy importante entender que:
Durante el desarrollo o un debug builds cualquiera de estas funciones detendra la ejecución de nuestra:
- assert
- assertioFailure
- precondition
- preconditionFailure
- fatalError
Nuestra aplicación en el appstore o cualquier build con release configuración cualquiera de estas funciones detendra la ejecución de nuestra aplicacin:
- precondition
- preconditionFailure
- fatalError
Por lo que tenemos que tener mucho cuidado en que momento utilizamos alguna de estas funciones.
AssertioFailure Ejemplo
enum UserState {
case loggedIn
case loggedOut
}
func handleState(_ state: UserState) {
switch state {
case .loggedIn:
print("Hola")
case .loggedOut:
print("Adios")
@unknown default:
assertionFailure("Valor inesperado.")
}
}
Si realizamos un cambio en nuestro codigo y agregamos una nueva propiedad, el tener este comportamiento por defecto en nuestro codigo y lanzando un crash en desarrollo nos permitira rapidamente saber que tenemos que realizar un cambio de implementacion.
func handleNotification(_ userInfo: [AnyHashable: Any]) {
guard let type = userInfo["type"] as? String else {
assertionFailure("Type es requerido")
return
}
print("notification type: \(type)")
}
Durante el desarrollo nos podemos encontrar que un valor que estamos esperando y que deberia llegar no esta llegando.
El assertionFailure no ayudara a detectar estos posibles errores lo antes posible. Lo bueno es que en caso de que pasemos por alto algun error, la aplicacion no hara crash en produccion.
fatalError Ejemplo
struct Config {
let apiKey: String
init(apiKey: String) {
guard !apiKey.isEmpty else {
fatalError("API key Invalida")
}
self.apiKey = apiKey
}
}Este es buen ejemplo donde deberiamos usar un fatalError, que si haria crash de nuestra aplicacion en produccion, dado que el apiKey es obligatorio para que nuestra aplicacion funcione como tal.
La moraleja
No todos los crashes son malos. Algunos son recordatorios de que tu código necesita atención.
- Usa
assertyassertionFailurecomo tus alarmas de desarrollo. - Reserva
fatalErrorpara condiciones críticas que no pueden ignorarse. - Y recuerda: un crash a tiempo puede ahorrarte horas de debugging en producción.

Referencias
https://developer.apple.com/documentation/swift/fatalerror(_:file:line:)
https://developer.apple.com/documentation/swift/assertionfailure(_:file:line:)