KATADE

  • GENERAL
  • WEB
    • Elixir
    • Php
    • Ruby on Rails
  • MOBILE
    • Android
    • iOS
  • NOVEDADES
    • Actualidad
    • Dev Inside
    • Eventos
    • Top 5
  • CONOCE A…

Follow Us

KATADE

  • GENERAL
  • WEB
    • Elixir
    • Php
    • Ruby on Rails
  • MOBILE
    • Android
    • iOS
  • NOVEDADES
    • Actualidad
    • Dev Inside
    • Eventos
    • Top 5
  • CONOCE A…
iOS,

Aprendiendo Swift – Opcionales

by Katade9 months agono comment
0
Shares
Share on FacebookShare on Twitter
Swift

Introducción

En el primer por sobre Swift hablamos de los tipos que existen destacando que en Swift no existe null. En Swift no existen las variables o constantes sin valor.

¿Que hacemos entonces si queremos declarar una variable con valor desconocido? ¿Y si una función falla y no devuelve nada?

¿Qué es un opcional?

Para resolver este, y muchos otros tipos de problemas Swift incorpora un modificador sobre las variables que es esencial al trabajar con este lenguaje: los opcionales.

Un valor opcional es un contenedor que puede tener dos valores: nada o algo. Mientras una variable o constante en Swift solo puede almacenar algo, pero nunca puede estar vacío; un opcional es un contenedor dentro de otro. Una variable opcional es como el gato de Schrödinger: puede que al abrir la caja en su interior encontremos un valor o puede que no. Hasta que no miremos dentro no lo sabremos.

Solo podemos utilizar opcionales con variables y no es posible inferir el tipo si las inicializamos vacías:

var hola = nil

Esto no funciona, debemos añadir el tipo:

var hola:String? = nil

Si te fijas, para convertir la variable en opcional simplemente añadimos una interrogación tras el tipo del dato.

Llegados a este punto es importante que entiendas que nil no es un valor válido para el tipo String, no podemos hacer:

var hola:String = nil

Al añadir la interrogación creamos un tipo nuevo que Swift trata de forma distinta. Un String opcional no es lo mismo que un String.

Si ahora modificamos el valor de esta variable opcional, vemos mejor cómo funcionan los opcionales por debajo:

var hola:String? = nil

 

hola = “Hola mundo”

 

print(hola)

Al hacer print vemos que no aparece “Hola mundo”, sino que aparece Optional(“Hola mundo”). Con esto podemos ver que nuestro valor está en realidad dentro de una caja, pero la lógica de Swift se encarga de que el proceso de asignación a esa “caja” sea transparente para nosotros.

¿Cómo accedemos entonces al valor?

Siguiendo con el ejemplo de la caja, si queremos obtener su valor debemos desempaquetar esa caja (unwrap en inglés, una palabra que leerás mucho aprendiendo Swift). Para ello podemos usar el símbolo ! que permite desempaquetar de manera implícita:

var hola:String? = nil

 

hola = “Adios”

 

print(hola!)

Al hacer ese cambio el resultado por consola ya no es un Optional. ¡Cuidado! Hacer un desempaquetado implícito o implicitly unwrap puede tener consecuencias desagradables. SOLO debemos usar ! cuando estemos seguros de que el opcional tiene contenido. Intentar acceder a un opcional vacío provocará un error en tiempo de ejecución:

var hola:String? = nil

 

print(hola!)

¿Cómo controlar entonces el valor de un opcional si no tenemos claro que tenga contenido? ¿Cómo saber si el gato está vivo o muerto sin abrir la caja? Para ello utilizaremos enlaces opcionales u “optional bindings”.

Enlaces opcionales

Una variable opcional puede tener dos valores:

  • Optional(valor)
  • nil

La ventaja de nil es que podemos utilizarlo en una condición booleana, es decir, si evaluamos un opcional y es nil nos devolverá false, y si tiene un dato que no sea vacío devolverá true. Esta acción no cambia el valor del opcional a ningún otro contexto impidiendo el fallo que hemos visto antes. No abrimos la caja, solo preguntamos por su estado: ¿Contiene un regalo?

Aprovechando esto podemos realizar un enlace opcional que asigna a una constante normal (no opcional ni variable) un valor opcional. Si el opcional tenía contenido, se ejecutará el ámbito dado pasando esa constante con el valor desempaquetado (unwrapped):

var regalo:String?

 

if let contenido = regalo{

   print(“Cotiene \(contenido)”)

}else{

   print(“No hay nada :(“)

}

Si el regalo es nil, la condición no se cumple y vamos directos al else.

var regalo:String?

 

regalo = “Un coche!”

 

if let contenido = regalo{

   print(“Cotiene \(contenido)”)

}else{

   print(“No hay nada :(“)

}

Pero, si por el contrario, tenemos un valor guardado, entraremos en el if con el valor desempaquetado en la constante contenido.

Tras entender cómo desempaquetar un opcional, al ir usándolos nos encontramos con un problema que se hizo famoso hasta que fue resuelto en Swift 2:

var regalo1:String?

var regalo2:String?

var regalo3:String?

 

if let regalo1 = regalo1{

   if let regalo2 = regalo2{

       if let regalo3 = regalo3{

           

       }

   }

}

Bonito, ¿verdad? Es lo que se conoce como “pirámide del mal”, una de las prácticas menos eficientes en programación. En Swift es posible resolver esto encadenando cada enlace separándolo por comas:

if let regalo1 = regalo1, let regalo2 = regalo2, let regalo3 = regalo3{

   print(“todos los regalos tienen algo”)

}

También podemos añadir una condición tanto en los enlaces simples como en los anidados:

if let regalo1 = regalo1, regalo1 == “Coche”{

   print(“Es un coche”)

}

 

if let regalo1 = regalo1, let regalo2 = regalo2, let regalo3 = regalo3, regalo3 == “Moto”{

   print(“todos los regalos tienen algo y el último es una moto”)

}

En ambos casos, con múltiples enlaces opcionales hemos incluido let en cada enlace, pero es posible simplificar y reducir así la cantidad de código:

if let regalo1 = regalo1, regalo2 = regalo2, regalo3 = regalo3{

   print(“todos los regalos tienen algo y el último es una moto”)

}

El enlace opcional se usa continuamente en Swift, es importante que lo aprendas bien y, sobre todo, que evites forzar el desempaquetado.

Control de flujo de opcionales

Al introducirnos en el mundo de Swift hablamos del concepto de ámbito. Un enlace opcional crea un nuevo ámbito y la constante desempaquetada sólo existe dentro de ese ámbito. Esto implica que el valor tras el if let sigue estando empaquetado:

var regalo:String?

 

regalo = “iPad pro”

 

if let regalo = regalo{

   print(regalo)

}

print(regalo)

Para solucionar este problema en casos dónde sea necesario podemos usar el control de flujo “guard”, también llamado anti-if.

Lo que hace esta instrucción es romper la ejecución si no se da una condición. Su uso más común es prevenirnos frente a un error de desempaquetado. Con un ejemplo es más fácil de entender:

guard let regalo = regalo else {return}

Si el regalo está vacío, se ejecutará el ámbito con el return, impidiendo así que el código que queda por debajo se ejecute. En caso contrario, el código se ejecutará pero además contaremos con el regalo desempaquetado. Este ejemplo fallará en el playground, ya que no es posible hacer un return directamente en el ámbito principal del playground. En lugar de return podríamos utilizar break, continue e incluso throw para lanzar un error. Guard es una forma de asegurarnos antes de ejecutar el resto del código de que una condición se cumple. En muchos casos su uso se puede solapar con el del if, pero en este caso concreto de desempaquetado de un opcional en el propio ámbito se entiende muy bien su porqué.

Operador de coalescencia nula

No hablamos de este operador en el post sobre operadores porque está directamente relacionado con los opcionales. Es un operador muy sencillo representado por dos interrogaciones. Su función es desempaquetar un opcional y, en caso de que no tenga algo dentro, devolver un valor por defecto situado al lado derecho del operador:

var paquete:String?

 

let regalo = paquete ?? “Nada”

Si el paquete no trae un regalo me quedo con nada. Su resultado es similar a utilizar un operador ternario condicional evaluando si es nil y devolviendo en caso contrario el valor desempaquetado.

Encadenamiento de opcionales

Es muy posible que en nuestros desarrollos con Swift nos encontremos con la necesidad de acceder a una propiedad de un objeto opcional, o más complicado aún, a la propiedad de un objeto opcional que a su vez es propiedad de un objeto opcional… Solo la explicación ya marea y podemos imaginarnos la implementación como algo así:

if let propiedadA = propiedadA,

   let propiedadB = propiedadA.propiedadB{

   

}

No queda especialmente bonito. Si la propiedad que necesitamos esta a 4 niveles (aunque acceder a tanta profundidad de un objeto ya no es recomendable) nos vamos a encontrar con una enorme cantidad de enlaces opcionales y un código muy difícil de seguir. Para evitar este tipo de problemas existe el encadenamiento de opcionales, transformando el caso anterior en este:

if let propiedadB = propiedadA?.propiedadB{

   

}

Al añadir la interrogación indicamos al compilador que solo debemos intentar evaluar propiedadB si propiedadA existe. También es posible utilizar el operador de desempaquetado implícito pero recuerda: solo debe usarse en casos concretos y siempre con la certeza de que ese dato existe. Siempre es mejor utilizar el operador condicional y conservar la seguridad que nos aporta Swift:

if let propiedadB = propiedadA!.propiedadB{

   

}

¿Por qué opcionales?

Muy posiblemente te estés preguntado ahora mismo si todo esto de los opcionales no es mucho lío. Seguramente pienses que sería mejor permitir utilizar el valor nil directamente como ocurre en otros lenguajes.

Podría ser más fácil, pero no más seguro y tampoco aplicable a todos los casos. El tipo opcional tiene una función muy clara: asegurar una mejor calidad del código por parte de los programadores y evitar errores mayores, sobre todo en tiempo de ejecución.

En otros lenguajes una variable vacía no es un error. Esto significa que, si nuestro programa tiene un error en su ejecución porque un objeto se queda vacío, será difícil de detectar ya que es posible que el error aparezca por otro lado. Swift transfiere la responsabilidad de gestionar bien las variables que puedan ser nil al desarrollador y obliga a utilizar mecanismos que permitan gestionar mejor casos no esperados, como encontrar una variable vacía que casi siempre no lo está. Por supuesto, es posible utilizar mal la herramienta y realizar desempaquetados implícitos por todas partes (!!!!!)… Pero aún así el error será más fácil de detectar.

Previous

Desarrollo Kotlin IV: edición frontend, interactuando con layouts

9 months ago
Next

¿Cómo aumentar el tráfico hacia tu web con SEO Local?

9 months ago

Leave a Reply Cancel reply

WEB

  • Tipos de conexiones a bases de datos MYSQL desde PHP

    Tipos de conexiones a bases de datos MYSQL desde PHP

    October 31, 2016
  • ActiveModel Serializer, una alternativa a JBuilder

    ActiveModel Serializer, una alternativa a JBuilder

    August 9, 2016
  • Elixir & Phoenix, el nuevo Lamborghini de los lenguajes

    Elixir & Phoenix, el nuevo Lamborghini de los lenguajes

    July 19, 2016
  • ActionCable en Rails 5: Web en tiempo real

    ActionCable en Rails 5: Web en tiempo real

    June 21, 2016
  • Migración en MySQL y Rails sin 'downtime'

    Migración en MySQL y Rails sin 'downtime'

    May 27, 2016

iOS

  • Aprendiendo Swift – Opcionales

    Aprendiendo Swift – Opcionales

    9 months ago
  • Aprendiendo Swift – Controles de flujo

    Aprendiendo Swift – Controles de flujo

    9 months ago
  • Aprendiendo Swift – Operadores

    Aprendiendo Swift – Operadores

    9 months ago

ANDROID

  • Desarrollo Kotlin IV: edición frontend, interactuando con layouts

    Desarrollo Kotlin IV: edición frontend, interactuando con layouts

    9 months ago
  • Desarrollo Kotlin (III): edición componentes generales del lenguaje

    Desarrollo Kotlin (III): edición componentes generales del lenguaje

    9 months ago
  • Desarrollo Kotlin (II): edición ¡Hola Mundo!

    Desarrollo Kotlin (II): edición ¡Hola Mundo!

    9 months ago

GENERAL

  • Las tendencias del mercado que impulsan el interés sobre la ciencia de los datos

    Las tendencias del mercado que impulsan el interés sobre la ciencia de los datos

    7 months ago
  • ¿Cómo aumentar el tráfico hacia tu web con SEO Local?

    ¿Cómo aumentar el tráfico hacia tu web con SEO Local?

    9 months ago
  • Urls amigables: ¿Por qué y cómo usarlas?

    Urls amigables: ¿Por qué y cómo usarlas?

    9 months ago

NOVEDADES

  • Nace ToroDB, la primera base de datos 100% española

    Nace ToroDB, la primera base de datos 100% española

    December 5, 2016
  • Codemotion 2016, el mayor evento nacional sobre desarrollo

    Codemotion 2016, el mayor evento nacional sobre desarrollo

    November 28, 2016
  • Codemotion Spain 2016, un reencuentro entre comunidades

    Codemotion Spain 2016, un reencuentro entre comunidades

    November 10, 2016
  • PyConEs 2016: pitonisas en Almería

    PyConEs 2016: pitonisas en Almería

    November 4, 2016

CONOCE A…

  • GDG Madrid apuesta por España a nivel tecnológico

    GDG Madrid apuesta por España a nivel tecnológico

    December 26, 2016
  • José Luis Esteban: "Aprender Haskell era como empezar de cero"

    José Luis Esteban: "Aprender Haskell era como empezar de cero"

    October 27, 2016
  • Daniel Latorre: "Soy más feliz trabajando por mi cuenta"

    Daniel Latorre: "Soy más feliz trabajando por mi cuenta"

    October 26, 2016

© 2017 Katade. All rights reserved.