Cursos

Swift 2, Lección 2: Controles de flujo y opcionales

Compra "Aprendiendo Swift 3"

La presente lección está probada y certificada en su funcionamiento con la versión 7 o superior de Xcode y corresponde a la especificación 2 y 2.1 del lenguaje Swift.

Bienvenidos a esta nueva entrega que, junto a la primera lección que ya se publicó, supone un conjunto de conocimientos que os permitirán crear vuestros primeros programas completos.

En esta lección veremos otros dos elementos fundamentales para crear cualquier programa: las instrucciones de flujo de control como bucles o condicionales y las variables opcionales.

Pero antes de nada, y por lo que pueda pasar, vamos a importar las clases principales del sistema, con la instrucción:

If y switch

La forma de condicionar un flujo de ejecución, para hacer que nuestro programa ejecute o no determinadas partes de código, se hace con las instrucciones if y switch. El primero es una simple condición (si x es igual a y, haz z) y el segundo es lo que se denomina una sentencia case, o lo que es lo mismo, un listado de posibles, con un conjunto de instrucciones en caso de cumplirse una de estas condiciones (dependiendo del valor de x, si es 1 haz esto, si es 2 esto otro, si es 3 lo de más allá. Si no es ninguno de estos, entonces nada).

Vamos a suponer que tenemos nuestro array de la lección anterior con nuestra colección de Los Vengadores. Y queremos saber si el que ocupa el índice 1 es Thor o saber si tiene más de 6 Vengadores en nuestra lista:

En la primera pregunta, si esta condición devuelve VERDADERO quiere decir que se cumple, el código entre llaves se ejecutaría, si no, simplemente pasaría de largo sin entrar dentro y continuaría con la siguiente instrucción tras la llave de cierre.

En la parte de abajo, preguntamos por la propiedad .count del array Vengadores, que nos devuelve un número con el total de valores que tiene esta matriz. Con el símbolo mayor qué, preguntamos si el valor es mayor que 6 (7 o más) y ponemos entre llaves lo que queremos que se ejecute. La instrucción else permite definir un flujo alternativo en caso que la condición no se cumpla: si el total de Vengadores es igual a 6 o inferior, se ejecutará el código que hay entre llaves tras la palabra else. Básicamente es un “o si no…”.

Cuando preguntamos por una comparación, hemos de usar dos símbolos de igual == que corresponden al protocolo de comparación. Este verifica si un objeto o valor es idéntico a otro en su contenido y/o orden (si aplica). De esta forma, el = es solo protocolo de asignación y se evitan errores. El resto de comparaciones son menor <, mayor >, mayor o igual >=, menor o igual <= o el diferente que es el no igual !=.

Si nos fijamos, if solo acepta una condición o su contraria, pero ¿qué pasa si queremos hacer diferentes cosas en función de diferentes posibles condiciones para una misma variable? Para eso usamos switch.

Cada vez que ejecutemos este código, la variable indice se cargará con un valor aleatorio entre 0 y el total de valores que hay en Vengadores, de forma que cada vez dará un mensaje diferente. En el caso de Ojo de Halcón y Viuda Negra, vemos que hay una doble condición. Swift permite en este tipo de sentencias, poner varias condiciones en un mismo case, separados por comas, y hará una condición de forma que si el valor es uno u otro, entrará en dicho caso.

La palabra clave default hace la función del else en el if: si ninguno de los case se cumple, ejecutará lo que haya en default. Y ojo, si intentamos quitarlo, veremos que obtenemos un error. Dada la seguridad de Swift a la hora de crear código no se puede hacer una sentencia switch si no hay un default. En cuanto a las instrucciones, Swift ejecutará todo lo que haya tras los : del case que cumpla la condición que se está evaluando, hasta que encuentre otra palabra case en cuyo caso saltará hasta la llave de cierre de switch.

Y por si os pica la curiosidad, arc4random() es una función que devuelve un número aleatorio, el cual podemos acotar con el operador %. Pero esta función (que pertenece a C) devuelve un tipo UInt32 el cual hay que convertir a un Int de Swift, por eso va acotado con Int(arc4random()) (lo que se llama una operación de casting o conversión de tipos). Luego le añadimos el operador % y el número en que queremos acotarlo. De esta forma obtendremos un número aleatorio entre 0 y el número que digamos. Pero ojo, si el número es 6 (por ejemplo) el aleatorio será entre 0 y 5, porque el operador % establece el rango máximo en exclusión (es decir, no se incluye entre la selección de dicho rango).

For in, repeat while

Siguiente paso: bucles. Un bucle es un trozo de código que se repite n veces. Puede servir para recorrer todos los valores de un array (lo que llamamos enumeración de un array) o para ejecutar ininterrumpidamente un trozo de código hasta que dentro de este se cumpla una condición determinada o porque queremos hacer algo repetitivo un número determinado de veces. Las veces pueden conocerse de antemano o establecerse según valores que solo se conocen en tiempo de ejecución del programa.

Nada más sencillo. Enumerar Vengadores en todos sus valores y por orden, es tan fácil como decir que tenemos una variable v donde queremos que se almacenen los valores de Vengadores. Luego imprimimos v y tendremos un listado de todos ellos. Incluso podemos hacer un truco y usar la función .reverse() que devuelve un array a la inversa, y obtendremos una lista invertida.

El código que hay entre las llaves que contiene el for in, se ejecutará tantas veces como elementos tenga Vengadores, recuperando en cada vuelta un valor diferente del array, desde el primer elemento (índice 0) al último (índice 5).

Como valor para in, podemos dar un rango prefijado o establecido por el valor de una variable entera. En este caso estamos viendo un recorrido de 1 a 20, incluyendo el rango máximo (hasta 20, inclusive). O también podemos usar el método .stride(through: 10, by: 2) (que forma parte del protocolo de los datos numéricos) que nos permite recorrer un rango de un valor x hasta un valor y, realizando saltos en dicho recorrido establecidos por z. En el caso del ejemplo de 1 a 20, de 2 en 2. También podemos probar a cambiar el rango completo … por el de máximo excluyente ..<, y ver como recorre del 1 al 9, sin incluir el 10.

En el último caso, creamos un for de 3 parámetros: el primero es la variable que vamos a usar, que además ha de ser definida, el segundo la condición de fin y el tercero qué va a ejecutarse en cada nuevo ciclo. En el ejemplo declaramos una variable i con valor igual a 0, establecemos una condición de salida en el que i sea menor o igual a 10 y le decimos que en cada vuelta del for se aumente en 1 el valor de i.

Notar que i++ aumenta el valor de i en 1: es un operador de incremento de valor. Si queremos incrementar el valor de i en 4, por ejemplo, indicaríamos i+=4. También podemos hacer la asignación como ++i lo que en una asignación aumentará primero el valor y luego lo devolverá. En resumen: si i es igual a 5, var a = i++ hace que a sea igual a 5 e i aumenta su valor a 6 después de asignarse a: a será igual a 5 e i a 6. Pero si hacemos var a = ++i el valor de a se asigna después de incrementar i, por lo que a sería 6 e i sería 6 también. El operador de incremento también puede ser substracción, por lo que -- restará 1 y -= restará un valor concreto a una variable. También pueden usarse variables en vez de valores enteros que incrementan o decrementan en más o menos de 1: a += b.

Lo que hace for in es simple: a la variable que sigue a la palabra clave for se le asigna en cada recorrido del bucle un valor que comprende los rangos, valores o recorridos que se indiquen tras la palabra in. O en el caso del for de tres pasos, creada e inicializada una variable de trabajo en la primera parte, se establece una salida cuando la condición de la segunda parte sea verdad y en cada vuelta se ejecuta el comando de la tercera.

El caso de repeat while es muy diferente. Es un ciclo que se repite indefinidamente hasta que, al final del mismo, se cumpla la condición que indiquemos, suponiendo el fin de dicho ciclo y la salida de esas llaves.

En este pequeño ejemplo, elegimos un valor aleatorio del 0 al 19 y luego hacemos un bucle repeat while para repetir la elección de otro valor aleatorio de igual rango, que se repite hasta que vuelve a salir el mismo número. Como vemos el repeat establece la evaluación de diferencia != por lo que se repite lo que hay entre las llaves que contienen repeat while, mientras acierto sea diferente de valor.

Opcionales

Y este ejemplo ha servido para introducir un nuevo concepto: las opcionales. Como ya dijimos, Swift no admite valores vacíos de inicialización, pero sí podemos inicializar una variable sin saber qué valor tendrá en ese momento, si no que se establecerá en el futuro. Eso se hace con un ? tras el tipo de variable.

Con la interrogación, estamos indicando a Swift que la variable es de tipo Int, pero que aun no queremos o no podemos asignarle un valor, por lo que se le asignará automáticamente un valor nulo y se almacenará en un contenedor específico. Cuando queramos recuperar el valor (como en la impresión) hay que añadir el modificador ! para que extraiga de este contenedor opcional el valor y lo muestre tal cual. Es lo que se llama un unwrap o extraer de un contenedor opcional un valor que podría o no existir en el momento que se pregunta por él.

En nuestro ejemplo anterior, necesitamos que la variable valor esté creada antes de entrar al repeat while, pero es este bucle el que asignará el número aleatorio que le corresponderá. Si inicializamos valor dentro del bucle, este se crea en un contexto dentro de las llaves, por lo que no podremos preguntar por él fuera de estas (en la condición del while). Podríamos haberle puesto un valor de -1 y hubiera funcionado igual, pero no en todos los casos vamos a poder asignar un valor determinado a una variable y nos será necesario dejarla vacía porque ya se le asignará valor en un contexto diferente.

Una variable opcional SIEMPRE ha de ser una variable var que pueda ser modificada. No tiene sentido hacerlo con una constante ( let) pues estas ya tienen su propia forma de predefinirse y luego establecer un valor, usando la tipificación..

Si probamos a comentar la línea que asigna a valor el número aleatorio dentro del repeat while, veremos que el código sigue funcionando pero entraremos en un bucle sin fin. Esto es debido a que valor tiene un valor (aunque sea uno vacío) que al definirlo como opcional se le ha introducido. Por lo tanto se procesará pero jamás coincidirá con acierto que sí tendrá un valor calculado por nosotros. Por lo tanto, hemos de tener cuidado de gestionar bien las variables.

Como ya dijimos, Swift incorpora muchas pequeñas características de este estilo que harán las aplicaciones o juegos mucho más estables de cara a fallos de ejecución, simplemente porque estos errores son dados en tiempo de compilación y no de ejecución, o porque las estructuras obligan a respetar unas determinadas condiciones, como el uso obligatorio de llaves o del default en la instrucción switch que permitirán que nuestro código sea mejor, más limpio y más seguro.

Fin de la lección

En esta lección hemos visto los controles de flujo, tanto condicionales con el if o el switch, así como los bucles for in y repeat while. Y además, hemos visto un concepto muy importante: las opcionales, un tipo de variable que tienen un valor vacío pero que Swift las trata de una forma muy especial para evitar errores. Con este conocimiento, podremos crear nuestros pequeños primeros programas, a la espera de la próxima lección donde veamos más cosas.

Espero que os haya sido de utilidad, que probéis mucho en el Playground haciendo vuestras propias pruebas, y solo emplazaos a la próxima lección. Si tenéis cualquier duda o problema, no dudéis en escribir un comentario o consultarnos a través del formulario de contacto o de cualquiera de las redes sociales. Estaremos encantados de atender vuestras dudas, opiniones o sugerencias. Hasta entonces, Good Apple Coding.

Compra "Aprendiendo Swift 3"

Etiquetas

Julio César Fernández

Analista, consultor y periodista tecnológico, desarrollador, empresario, productor audiovisual, actor de doblaje e ingeniero de vídeo y audio.

Artículos relacionados

Cerrar
Cerrar