ios - tiempo - Excepción de desenvolvimiento de fuerza rápida no propagada
manifestaciones de la fuerza explosiva (2)
Me he topado con este comportamiento tonto en Swift, donde el desenvolvimiento forzado de un opcional no se propaga.
De la documentación:
Tratando de usar! para acceder a un valor opcional no existente se genera un error de tiempo de ejecución. ¡Siempre asegúrese de que un opcional contenga un valor no nulo antes de usar! Para forzar-desenvolver su valor.
Reproducir:
func foo(bar:String?) throws{
print(bar!);
}
Y
try foo(nil);
Esto no me parece lógico ni coherente y no puedo encontrar ninguna documentación sobre este tema.
¿Es esto por diseño?
De la documentation :
Manejo de errores
El manejo de errores es el proceso de responder y recuperarse de las condiciones de error en su programa. Swift proporciona soporte de primera clase para lanzar, capturar, propagar y manipular errores recuperables en tiempo de ejecución.
...
Representar y lanzar errores
En Swift, los errores están representados por valores de tipos que se ajustan al protocolo
ErrorType
. Este protocolo vacío indica que se puede usar un tipo para el manejo de errores.
(Nota: ErrorType
ha sido renombrado a Error
en Swift 3)
Así que con try/catch
usted maneja los errores de Swift (valores de tipos que se ajustan al protocolo ErrorType
) que son throw
n. Esto no tiene NSException
relación con los errores de tiempo de ejecución y las excepciones de tiempo de ejecución (y tampoco con la NSException
de la biblioteca de Foundation).
Tenga en cuenta que la documentación de Swift sobre el manejo de errores ni siquiera utiliza la palabra "excepción", con la única excepción (!) En (énfasis mío) en:
NOTA
El manejo de errores en Swift se parece al manejo de excepciones en otros idiomas, con el uso de las palabras clave try, catch y throw. A diferencia del manejo de excepciones en muchos idiomas, incluido Objective-C, el manejo de errores en Swift no implica el desenrollamiento de la pila de llamadas, un proceso que puede ser computacionalmente costoso. Como tales, las características de rendimiento de una declaración de lanzamiento son comparables a las de una declaración de devolución.
El desenvolvimiento de los opcionales que son nil
no produce un error Swift (que podría propagarse) y no se puede manejar con try
.
Debe utilizar las técnicas más conocidas, como el enlace opcional, el encadenamiento opcional, la comprobación contra nil
etc.
este ejemplo ''autoexplicativo'' puede ayudarlo a ver la diferencia entre generar una excepción de tiempo de ejecución y lanzar un error E conforme al protocolo ErrorType.
struct E: ErrorType{}
func foo(bar:String?) throws {
if let error = bar where error == "error" {
throw E()
}
print(bar, "is valid parameter, but don''t try to access bar.characters, it crash your code! (if bar == nil)")
// here is everything OK
let bar = bar!
// but here it crash!!
_ = bar.characters
}
do {
try foo("error")
// next line is not accessible here ...
try foo(nil)
} catch {
print("/"error/" as parameter of foo() throws an ERROR!")
}
do {
try foo(nil) // fatal error: unexpectedly found nil while unwrapping an Optional value
} catch {
}
se imprime
"error" as parameter of foo() throws an ERROR!
nil is valid parameter, but don''t try to access bar.characters, it crash your code! (if bar == nil)
fatal error: unexpectedly found nil while unwrapping an Optional value
elevar una excepción de tiempo de ejecución es un error fatal en su código.