Swift logotipo

En anteriores post, tuviste la ocasión de empezar a aprender algunos de los conceptos básicos del lenguaje de programación en Swift. Además, si has practicado con la APP de Apple de “Swift Playgrounds” comprenderás mejor laque viene a continuación. Y si aparte de haber practicad con el juego, posees conocimientos de programación, te darás cuenta que existen algunas similitudes con otros lenguajes de programación, como el Ruby, el JavaScript, Objective-C, Arduino u otros. ‎

‎En este post llamado «Swift – Opcionales, nil y bucles» nos centraremos en lo que se conoce por “flujo de control”. Pero antes de explicar detalladamente qué es el concepto de “flujo de control”, debemos comprender un concepto  previo que en su mayoría es nuevo, los “opcionales”. Los opcionales son algo que da seguridad en el lenguaje Swift. Al principio, puede parecer engorroso emplear tales opcionales, sin embargo, comprenderá en seguida, que los opcionales ofrecen seguridad al código. ‎

‎Opcionales‎

‎Previamente se ha visto que una variable debe inicializarse antes de poder usarse. Esto sucede en una gran mayoría de lenguajes de programación. Por ejemplo, hasta ahora hemos visto algo como:

var nombrePersona = “Pablo

Sin embargo, no siempre es necesario inicializar una variable en un código. Es decir, no siempre es necesario ponerle un string, un “int” o un bool a una variable. Veamos el siguiente ejemplo para comprender mejor lo que esto significa. ‎

var palabra: String
palabra.isEmpty

Si ha programado con Strings en otros lenguajes de programación, posiblemente le sorprenda que Swift lo califique de erróneo. Pruebe y vea qué sucede. 

El error indica que la variable “palabra” debe inicializarse. Eso sucede porque en multitud de lenguajes de programación, las variables deben de poseer un valor inicial.

En algunos lenguajes como Arduino podemos declarar una variable, por ejemplo, “int unEntero;” sin ningún valor asociado porque el compilador de Arduino entiende que se inicializa con valor nulo y posteriormente se “llenará” con otro valor. 

Definición de Opcional

El lenguaje ‎Swift emplea los opcionales para indicar que una variable o una constante puede tener un valor o no tenerlo. Si deseamos declarar una variable o una constante como opcional, sólo hace falta agregar un signo de interrogación al tipo de variable o constante. ‎

var texto: String?

‎La variable “texto” ahora es un “String” de tipo ‎‎opcional. El efecto resultante de convertir una variable en opcional, es que no podremos trabajar directamente con el valor de la variable. El valor se guarda de forma segura en el opcional, y tenemos que pedir al opcional el valor que encapsula. 

Por ejemplo, hay personas que pueden o no tener un segundo apellido. Por lo que el segundo apellido es opcional, es decir, es posible que no se le asigne ningún valor. En cuyo caso su valor será “nil” (nulo). 

El “nil” sólo se asigna a variables o constantes opcionales. En el resto de los casos carece de sentido. 

Desencapsulamiento forzado (Forced Unwrapping)

Una forma de acceder al valor de un opcional es “forzando” un desencapsulamiento. Es decir, sólo se podrá acceder al valor de la variable “texto” añadiendo un símbolo de exclamación “!” al nombre de la variable.

var texto: String?
texto = "prueba" 
print(texto!)

Es importante que esté seguro que al opcional en algún momento se le ha proporcionado previamente un valor o un dato cuando fuerza el desencapsulamiento. Si el opcional no contiene ningún valor y lo desencapsula, Swift te lanzará un error. En este caso sino se pone la exclamación “!”, lo que sucederá es que Xcode, dará un “Warning”.

Enlace opcional

Hay otra forma de acceder al valor de un opcional para evitar errores. Aunque posteriormente analizaremos las instrucciones “if”, es fácil de entender lo que pretende el siguiente ejemplo. Aquí lo que se pretende es acceder al valor almacenado en la variable “String” opcional llamada “palabra”.

var palabra: String?

if palabra != nil {
    print(palabra!)
} else {
    print("palabra no tiene valor")
}

Lo que hace este ejemplo es primero comprobar si la variable “palabra” es igual “nil”. Si realmente contiene un valor, se imprimirá éste. En caso contrario, se imprimirá la “palabra no tiene valor”

Hay un enfoque mas formal llamado “optional binding”. En el siguiente ejemplo, asignamos el valor almacenado en el opcional a una constante temporal, que se utiliza en la instrucción “if”. El valor del opcional “palabra” está enlazado a la constante “palabraConstante” y se utiliza en la instrucción “if”. Este enfoque también funciona para las declaraciones “while”. 

var palabra: String?
palabra = "Prueba"

if let palabraConstante = palabra {
 print(palabraConstante)
} else {
 print("palabra carece de valor")
}

En la consola veremos impresa la palabra «prueba».

Definición de nil

Si proviene de algún otro lenguaje, como el Objective-C, entonces seguramente conoce lo que significa “nil”. El “nil” en Objective-C, se refiere a un puntero a un objeto inexistente. Sin embargo, Swift define “nil” de forma diferente.

En Swift, “nil” es la ausencia de cualquier valor. Si bien “nil” sólo es aplicable a objetos, en Objective-C, en Swift se puede usar “nil” para cualquier tipo.

El Flujo de control

Swift ofrece una serie de constructores comunes a otros lenguajes de programación para controlar el flujo del código que se escribe. Si posee alguna experiencia en programación, entonces no tendrá problemas para comprender los condicionales “if” y “switch”, las sentencias y los bucles “for” y “while”.

El estamento “IF”

Las declaraciones “if” de Swift son muy parecidas a las que se encuentran en otros lenguajes de programación. La sintaxis de un “if” se basa en las siguientes características: 

  • No hay necesidad de envolver la condición “if” entre paréntesis. 
  • Los corchetes, sin embargo, son obligatorios. Esto evita que los desarrolladores introduzcan errores comunes que están relacionados con la escritura de declaraciones sin corchetes. 

Así es como se ve una declaración “if” en Swift:

let a = 100

if a > 100 {
   print("El valor de \"a\" es mayor que 100.")
} else {
   print("El valor de\"a\" es menor o igual a 100.")
}

Swift, al igual que en otros lenguajes, tiene la cláusula “else” que se ejecuta si la condición es igual a “false”. También es factible encadenar instrucciones condicionales del tipo “if” como se muestra a continuación. 

let a = 100

if a > 100 {
print("El valor de \"a\" es mayor que 100.")
} else if a > 50 {
       print("El valor de \"a\" es mayor que 50.")
} else {
       print("El valor de \"a es menor que 50.")
}

Es importante tener en cuenta que un “if” entrega un “true” o “false”. Y para ello, no hay que suponer nada. Es decir, si ponemos un código como el que sigue, obtendremos un error. En otras palabras para evitar errores es recomendable siempre emplear operadores lógicos: igual, mayor que, menor que, diferente, etc. 

En otros lenguajes, el compilador interpretaría que array.count tiene un valor igual o mayor que 0. Sin embargo en Swift hay que poner un array.count > 0. Es decir, hay que forzar la condición. 

let cadena = [String]()

if cadena.count > 0 {
    print("El array contiene más de un elemento.")
} else {
    print("El array está vacío.")
}

El estamento switch o estructura selectiva múltiple

Las declaraciones “switch “en Swift comparten la misma funcionalidad que en otros lenguajes de programación; se pasa un valor a la instrucción y lo compara con posibles patrones de coincidencia. 

Un switch o estructura selectiva múltiple compara un valor con diversas alternativas. Cuando os valores coinciden se ejecuta el grupo de instrucciones pertenecientes a tal coincidencia. Una vez completadas tales instrucciones se sale de la estructura y continúa el flujo del programa. En visual basic se conoce por “select case”. 

El switch en swift y otros lenguajes de programación permite ahorrar tiempo de programación puesto que evita escribir y concadenar instrucciones del tipo “if…else”. 

Exhaustividad

La declaración “switch” en Swift debe ser exhaustiva, lo que significa que cada posible valor que se entrega a la instrucción “switch” debe ser manejado por la instrucción “switch”. Eso significa que se debe dar a swift todos los casos existentes, y para el resto de valores ponemos el “default”. Veamos: 

let z = 10

switch z {
case 10:
   print("z es igual a 10")
case 20:
    print("z es igual a 20")
default:
    print("Tiene otro valor")
}

En otras palabras, la exhaustividad es obligatoria en una instrucción “switch” y para ello hay que poner siempre un “default”.

Fallthrough (Caída o fracaso)

La caída o fracaso en Swift significa que el switch debe tener una instrucción por cada caso, sino obtendremos un error. Observemos el siguiente ejemplo “switch”.

let z = 10

switch z {
 case 10:
 case 20:
      print("z es igual a 10")
 default:
      print("Tiene otro valor")
}

El primer caso en el que “z” se compara con “10” no prosigue hacia al segundo caso en el que “z” se compara con “20”. Si copia y pega el ejemplo anterior en Playground, se dará cuenta que Swift le arroja un error: «‘case’ label in a ‘switch’ should have at least one executable statement» Este error significa que cada caso debería incluir cómo mínimo una instrucción ejecutable. 

Observe que en las declaraciones “Switch” no incluyen los típicos “break” para salir de dicha declaración “switch”. En Swift no son necesarios los “break”, ya que la caída implícita no existe en Swift. Esto eliminará una serie de errores comunes causados por las caídas involuntarias. 

Patrones

La potencialidad de una declaración “switch” en Swift radica en la coincidencia de patrones. Analicemos el siguiente ejemplo en el que se han empleado rangos para comparar un determinado valor.

let z = 10

switch z {
case 10..<50:
    print("El valor está situado entre 10 y 50.")
case 50...100:
    print("El valor está situado entre 50 y 100.")
default:
   print("El valor es mayor que 100.")
}

El operador de Swift “..<”  llamado de “rango entreabierto” establece un rango desde el primer valor dado hasta el segundo valor, excluyendo el segundo valor. El operador “…” llamado de “rango cerrado” define un rango que va desde el primer valor hasta el segundo valor, incluido el segundo valor. Dichos operadores son muy empleados en una amplia gama de situaciones.

También puede se puede comparar si una tupla está dentro de un rato. Veamos el siguiente ejemplo:

let laTupla = (54.65, -97.13)

switch laTupla {
case (0, 0):
    print("Nosotros estamos dentro la tupla.")
case (0...100, _):
    print("Estamos fuera de la Tupla.")
case (-100...0, _):
    print("Estamos muy lejos de la Tupla.")
default:
    print("Valores erróneos.")
}

El resultado sería: “Estamos fuera de la Tupla”. Cuando el valor coincida con más de un caso, se Swift coge el primer caso coincidente. El ejemplo anterior también ilustra el uso del guion bajo. Como vimos en el artículo anterior, podemos usar un guion bajo, “_”, para decirle a Swift qué valores NO debe tener en cuenta. 

En el siguiente ejemplo, el segundo valor de la tupla está enlazado a la constante “descripción” para su uso en el primer y segundo caso. 

var respuesta = (210, "HOLA")

switch respuesta {
       case (200..<500, let descripción):
    print("La respuesta fue correcta y describió \( descripción).")

       case (500..<600, let descripción):
    print("La respuesta fue correcta y describió \( descripción).")

       default:
    print("La respuesta fue incorrecta y no describió nada.")
}

Al final en la consola veríamos algo como: “la respuesta fue correcta y describió HOLA. 


El bucle “for”

El bucle “for” es el primer tipo de bucle que veremos. Se comporta de manera muy similar a los bucles “for” existentes en otros lenguajes de programación. Suelen existir dos tipos de bucles “for”, el bucle “for” propiamente y el bucle “for-in”. A partir de Swift 3, sin embargo, los bucles “for” de estilo C ya no están disponibles. El siguiente fragmento de código no es posible utilizarlo en Swift 3. 

for var a = 0; a < 100; i++ {
    print("a es igual a\(a).")
}

Sí copia y pega este fragmento en un Playground, observará que los operadores “++” y “–” ya no están disponibles en Swift 3.

El bucle “for-in” es perfecto para aplicarlo en rangos o colecciones. En el siguiente ejercicio, lo empleamos para pasar por los elementos de una matriz.

let numeros = [1, 2, 3, 5, 8]

for numero in numeros {
    print("El número es igual a \(numero)")
}

También se pueden usar los bucles “for-in” para hacer bucles sobre los pares clave-valor en un diccionario. En el siguiente ejercicio, imprimiremos el contenido de un diccionario en la consola. Como vimos anteriormente, la secuencia de los pares clave-valor no está definida puesto que un diccionario es un conjunto no ordenado de pares clave-valor.

var elDiccionario = ["Josep": 100, "Agata": 150, "Asnate": 120]

for (nombre, diccionario) in elDiccionario {
    print("\(nombre)'s diccionario es \(diccionario).")
}

El resultado en consola es:

  • Josep’s diccionario es 100.
  • Asnate’s diccionario es 120.
  • Agata’s diccionario es 150.

Cada par clave-valor del diccionario es accesible en el bucle “for-in” como una tupla de constantes con nombre. El bucle “for-in” también es excelente si se combina con los rangos.

for a in 1...100 {
    print(“a es igual \(a)")
}

while

El bucle “while” tiene dos versiones, el “while” y “repeat-while”. La principal diferencia radica en que el conjunto de instrucciones de un bucle “repeat--while” siempre se ejecuta como mínimo  una vez, porque la condición del “repeat–while” se evalúa al final de cada iteración. En el ejemplo siguiente se muestra tal diferencia. 

var a = 50
var b = 60

while a < b {
 print("a es menor que b")
}

repeat{
 print("a es menor que b")
   
}while a < b

La instrucción “print” del bucle “while” nunca se ejecuta, mientras que la del bucle “repeat–while” se ejecuta una vez. 

En multitud de casos, los bucles “for” se pueden reescribir como bucles “while”, y a menudo  es decisión del programador seleccionar qué tipo de bucle emplear en un determinado caso. Por ejemplo, con los siguientes bucles “for” y “while”  se obtiene el mismo resultado. 

Para el bucle for:

for a in 0..<100 {
    print(a)
}

Con el While:

var a = 0
while a < 100 {
    print(a)
   a += 1
}

En consolasen ambos casos, debería imprimir hasta 99.

Conclusión

La verdad es que el tema de los flujos en swift, es mucho más extenso. Recomendamos empezar con la APP de “Swift Playgrounds”. Es una manera divertida de familiarizarse con ello. Si además, se complementa con este post, el nivel alcanzado será mayor. 

Más información

Deseamos que te haya gustado este post de «Aprende a programar en Swift«. Si deseas más información sobre cómo programar en Swift Playgrounds consulta en la web oficial de Apple. Para cualquier otra consulta, puedes contactar con nosotros. También nos puedes ayudar descargando nuestra APP de Servicios Profesionales, freelancers y autónomos.

Leave a Comment

Your email address will not be published. Required fields are marked *

Información básica sobre protección de datos
Responsable Francisco de Asís Benavente Delgado +info...
Finalidad Gestionar y moderar tus comentarios. +info...
Legitimación Consentimiento del interesado. +info...
Destinatarios No se cederán datos a terceros, salvo obligación legal +info...
Derechos Acceder, rectificar y cancelar los datos, así como otros derechos. +info...
Información adicional Puedes consultar la información adicional y detallada sobre protección de datos en nuestra página de política de privacidad.