Al llamar a una función que se declara con throws
en Swift, debe anotar el sitio de llamada de función con try
o try!
. Por ejemplo, dada una función de lanzamiento:
func willOnlyThrowIfTrue(value: Bool) throws {
if value { throw someError }
}
Esta función se puede llamar así:
func foo(value: Bool) throws {
try willOnlyThrowIfTrue(value)
}
Aquí anotamos la llamada con try
, lo que indica al lector que esta función puede generar una excepción y que las siguientes líneas de código podrían no ejecutarse. También tenemos que anotar esta función con throws
, porque esta función podría lanzar una excepción (es decir, cuando se willOnlyThrowIfTrue()
lanza, foo
automáticamente volverá a lanzar la excepción hacia arriba).
Si desea llamar a una función que se declara como posiblemente lanzada, pero que sabe que no se lanzará en su caso porque le está dando la entrada correcta, puede usarla try!
.
func bar() {
try! willOnlyThrowIfTrue(false)
}
De esta manera, cuando garantiza que el código no se lanzará, no tiene que poner código extra repetitivo para deshabilitar la propagación de excepciones.
try!
se aplica en tiempo de ejecución: si usa try!
y la función termina lanzando, la ejecución de su programa terminará con un error de tiempo de ejecución.
La mayoría de los códigos de manejo de excepciones deben ser similares a los anteriores: o simplemente propaga las excepciones hacia arriba cuando ocurren, o configura las condiciones de modo que, de lo contrario, se descarten posibles excepciones. Cualquier limpieza de otros recursos en su código debe ocurrir a través de la destrucción de objetos (es decir deinit()
), o algunas veces a través del defer
código ed.
func baz(value: Bool) throws {
var filePath = NSBundle.mainBundle().pathForResource("theFile", ofType:"txt")
var data = NSData(contentsOfFile:filePath)
try willOnlyThrowIfTrue(value)
// data and filePath automatically cleaned up, even when an exception occurs.
}
Si por alguna razón tiene un código de limpieza que necesita ejecutarse pero no está en una deinit()
función, puede usarlo defer
.
func qux(value: Bool) throws {
defer {
print("this code runs when the function exits, even when it exits by an exception")
}
try willOnlyThrowIfTrue(value)
}
La mayoría del código que trata con excepciones simplemente hace que se propaguen hacia arriba a las personas que llaman, haciendo la limpieza en el camino a través de deinit()
o defer
. Esto se debe a que la mayoría del código no sabe qué hacer con los errores; sabe qué salió mal, pero no tiene suficiente información sobre lo que intenta hacer un código de nivel superior para saber qué hacer con el error. No sabe si presentar un diálogo al usuario es apropiado, o si debería volver a intentarlo, o si algo más es apropiado.
Sin embargo, el código de nivel superior debe saber exactamente qué hacer en caso de error. Por lo tanto, las excepciones permiten que surjan errores específicos desde donde ocurren inicialmente hasta donde se pueden manejar.
El manejo de excepciones se realiza mediante catch
declaraciones.
func quux(value: Bool) {
do {
try willOnlyThrowIfTrue(value)
} catch {
// handle error
}
}
Puede tener varias declaraciones catch, cada una de las cuales captura un tipo diferente de excepción.
do {
try someFunctionThatThowsDifferentExceptions()
} catch MyErrorType.errorA {
// handle errorA
} catch MyErrorType.errorB {
// handle errorB
} catch {
// handle other errors
}
Para obtener más detalles sobre las mejores prácticas con excepciones, consulte http://exceptionsafecode.com/ . Está específicamente dirigido a C ++, pero después de examinar el modelo de excepción Swift, creo que los conceptos básicos se aplican también a Swift.
Para obtener detalles sobre el modelo de sintaxis y manejo de errores de Swift, consulte el libro El lenguaje de programación Swift (Presentación preliminar de Swift 2) .