tutorial for español developer apple ios xcode swift

ios - for - xcode tutorial español



Swift 2: la llamada se puede lanzar, pero no está marcada con ''try'' y el error no se maneja (2)

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 , que le 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 willOnlyThrowIfTrue() throws, foo volverá a lanzar automáticamente 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 usar 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 lanzándose, entonces 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 tener el aspecto anterior: 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 de código deinit() .

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 función deinit() , puede usar 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 deinit() . 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 declaraciones catch .

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á dirigido específicamente 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) .

Después de instalar Xcode 7 beta y convertir mi código swift a Swift 2, tuve un problema con el código que no puedo entender. Sé que Swift 2 es nuevo, así que busco y descubro que no hay nada al respecto, debería escribir una pregunta.

Aquí está el error:

La llamada puede lanzarse, pero no está marcada con ''intentar'' y el error no se maneja

Código:

func deleteAccountDetail(){ let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!) let request = NSFetchRequest() request.entity = entityDescription //The Line Below is where i expect the error let fetchedEntities = self.Context!.executeFetchRequest(request) as! [AccountDetail] for entity in fetchedEntities { self.Context!.deleteObject(entity) } do { try self.Context!.save() } catch _ { } }

Instantánea:


Debe detectar el error tal como ya lo está haciendo para su llamada save() y dado que está manejando múltiples errores aquí, puede try varias llamadas secuencialmente en un solo bloque do-catch, de esta manera:

func deleteAccountDetail() { let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!) let request = NSFetchRequest() request.entity = entityDescription do { let fetchedEntities = try self.Context!.executeFetchRequest(request) as! [AccountDetail] for entity in fetchedEntities { self.Context!.deleteObject(entity) } try self.Context!.save() } catch { print(error) } }

O como señaló @ bames53 en los comentarios a continuación, a menudo es una mejor práctica no detectar el error donde se arrojó. Puede marcar el método como throws try llamar al método. Por ejemplo:

func deleteAccountDetail() throws { let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!) let request = NSFetchRequest() request.entity = entityDescription let fetchedEntities = try Context.executeFetchRequest(request) as! [AccountDetail] for entity in fetchedEntities { self.Context!.deleteObject(entity) } try self.Context!.save() }