Home » Cursos » Swift 2, Lección 2: Controles de flujo y opcionales
Curso Swift Lección 2

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"

Acerca de 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.

Otras recomendaciones

Lecciones Prototipos (I): UITableView

Lecciones por prototipos (I): Vistas de tabla (UITableView)

Primera lección por prototipos, un nuevo e innovador contenido. A veces, lo normal es que nos perdamos sin terminar de entender qué es o cómo funcionan los componentes que forman parte de una app o un juego. Para este caso hemos creado las lecciones por prototipos. Una exploración básica de conceptos esenciales a través de prototipos en Playground que podemos probar con Swift Playgrounds en el iPad o con Xcode 8. En esta primera lección abordamos las UITableView (vistas de tabla). Un elemento esencial en la mayoría de apps de iOS que muchas veces no es entendido desde su base y por lo tanto, provoca un mal uso de las mismas.

  • Buenas noches, cuando intento hacer uso del bucle for usando el stride, me esta dando el siguiente error.
    Use of unresolved identifier ‘stride’

    for num in stride(from:1, to:10, by:2) {
    println(“Recorremos los números (num)”)
    }

    posiblemente haya sido deprecado de versión en versión?

    Por favor podrían apoyarme?

    • Julio César Fernández

      Hola Kumikos,

      La función stride forma parte de Swift desde la versión Beta4 de Xcode 6. Necesitas esta versión para que el comando sea reconocido.

      Un saludo,

  • Una segunda consulta, que significa el signo ? al lado del tipo Int y el signo ! al lado de la misma variable en el sgte. codigo:

    var valor:Int?

    do {
    valor = Int(arc4random()) % 20
    if acierto != valor {
    println (“No he acertado. Ha salido el número (valor!)”)
    }
    } while acierto != valor

    • 🙂 ya no es necesario, por desesperado no lei todo el post 😀 muchas gracias, son variables opcionales y es como variables vacías que se llenaran a futuro 😀

  • Pingback: Lección 1: Variables, constantes, inferencia y colecciones | AppleCoding()

  • Pingback: Swift Lección 3: Clases, métodos, structs y herencia | Apple Coding()

  • Constan

    Muy buenas Julio.

    Antes de nada, agradecerte estas magnificas clases y desde un punto de vista completamente egoísta, animarte para que continúes la tarea, estoy deseando practicar la siguiente lección y me resultan muy enriquecedoras. Destacar que la forma que tienes de trasladar el conocimiento en pequeñas dosis, por lo menos en mi caso, ha conseguido crear una ansiedad importante de conocimiento respecto a este tema y se me hace muy larga la espera. Muchísimas gracias.

    Estaba practicando el ejercicio de la estructura “do while” en Playground con Xcode actualizado a la última versión (6.1), al comentar la linea donde asignamos valor a la variable “valor” dentro de las llaves del bucle, tal y como sugieres:

    var valor:Int?
    let acierto = Int(arc4random()) % 20
    println (“Buscando el número (acierto)”)
    do {
    // valor = Int(arc4random()) % 20
    if acierto != valor {
    println (“No he acertado. Ha salido el número (valor!)”)
    }
    } while acierto != valor
    println(“Enhorabuena. Salió el (valor!)”)

    no se ha producido el error de compilación y la ejecución ha continuado de forma indefinida, ¿a que puede ser debido?.

    Reiterarme en el agradecimiento.

    • Julio César Fernández

      Hola Constan,

      Muchas gracias por tu agradecimiento. Pronto iremos editando más contenido, pero supone mucho tiempo generar el mismo con la calidad suficiente y por eso los posts se alargan más de lo que quisiéramos, aparte que al acercarnos a Navidades, en Gabhel Studios estamos terminando de cerrar ¡3 proyectos diferentes!.

      En cuanto a tu duda dos cosas:
      1. El bucle se ejecuta indefinidamente porque la condición que hace que el do while deje de ejecutar (acierto != valor) nunca llega a cumplirse.
      2. En la última versión 6.1, las opcionales Int? (como está definido valor) tienen un valor nil implícito que da “por válida” esta variable (porque realmente nunca está vacía) pero como verás nunca conseguirá igualar el valor de “acierto” y por lo tanto nunca saldrá del bucle.

      Un saludo y mil gracias. Revisaremos el texto, no obstante, para aclarar este término.

  • Pingback: Swift Lección 5, Tuplas | Apple Coding()

  • Pingback: Curso de Swift Lección 6, Enumeraciones | Apple Coding()

  • .[Roberto Hevens]

    Julio:

    Excelente lección. Me doy cuenta como aprende uno a empezar a querer este lenguaje de programación.

    Un saludo.

  • Pingback: Swift 2 Lección 4: Funciones | Apple Coding()