Cursos

Swift 2, Lección 1, variables, constantes, inferencia y colecciones

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.

Primera lección del curso de Swift, donde aprenderemos los conceptos básicos del nuevo lenguaje de programación de Apple en cuanto a variables y constantes, su uso y declaración y qué es la inferencia de tipos que caracteriza a Swift y cuándo usarla. Si no leíste aun la introducción al curso te aconsejamos que lo hagas para que puedas seguir mejor está lección.

Variables y constantes (propiedades)

Una variable es un contenedor cuyo valor puede variar en el transcurso de la ejecución de nuestro programa. Una constante, por el contrario, es un valor que permanecerá inalterable (o inmutable) durante el mismo. Ambos tipos forman parte de lo que se llaman propiedades.

Es muy importante recordar que las propiedades en Swift 2 (variables o constantes) siempre han de inicializarse con un valor, no pueden dejarse vacías o sin valor asignado, pues el valor vacío no existe como tal. En caso de ser necesario, hay que usar el concepto de las opcionales, que veremos en una lección más adelante.

Las variables se definen con la palabra clave var antecediendo al nombre de la misma y las constantes con la palabra let. Como podemos ver en el ejemplo a la derecha, estamos definiendo dos variables que vamos a llamar manzanas y nombre. Estas variables tendrán para empezar un valor de 9 en manzanas y la cadena Antonio en nombre. Por el contrario peras y apellido son constantes y tendrán asignado un valor de 4 y la cadena Pérez, respectivamente.

Pero como vemos debajo, si luego queremos que manzanas pase a guardar un valor de 5, solo tenemos asignar el mismo. Pero peras, que es una constante, nos provocará un error pues su valor es, como se conoce en programación, inmutable. No puede variar en el transcurso de la ejecución del programa.

Podemos definir varias variables o constantes en una misma línea, separando cada nombre y su valor por una coma.

La notación correcta para definir valores es con un =. Los números se ponen tal cual y las cadenas o valores alfanuméricos han de ir entre comillas dobles " ". Si solo queremos definir un carácter, podemos hacerlo poniendo el valor entre comillas simples ' '. El separador de decimales siempre es el punto, por ejemplo, 3.1415.

Tipos de datos básicos

Las variables y constantes en Swift pueden ser de muchos tipos y complejidad en cuanto a estructura, pero al final todos tendrán una base en los llamados tipos de datos básicos, que nos permiten guardar los tipos de información más básicos que luego nos permitirán crear otros más complejos.

  • Int, número entero de 32 bits con un rango de entre -2.147.483.648 y 2,147,483,647.
  • Double, número flotante de 64 bits con hasta 15 decimales de precisión.
  • Float, número flotante de 32 bits con hasta 6 decimales de precisión.
  • Bool, número booleano que puede ser 0 (false) o 1 (true).
  • String, cadena de caracteres, tratada internamente con una matriz (array) de ellos.

Esto serían los tipos básicos que pueden ser usados a la hora de crear variables o constantes. Podemos declararlos indicando los tipos, siempre y cuando queramos tener claro qué contendrán o si queremos evitar que el compilador decida por nosotros.

Si nos fijamos en los ejemplos que dábamos al comienzo, estos no tenían puesto el tipo de dato que íbamos a usar. Y esto es porque hemos usado la inferencia de datos: la propiedad que tiene el compilador de determinar por nosotros cuál es el tipo de dato a usar en una variable o constante en función de su contenido. Tal como hemos indicado, salvo en casos que veremos más adelante, todas las propiedades han de ser inicializadas con un valor al comienzo, por lo que en ese momento es cuando se decide el tipo. De esta forma, nuestro último código quedaría así:

Tipos de datos complejos: colecciones

Hemos visto lo que se denominan tipos de datos básicos. Es decir, tipos cuyo contenido es el dato en sí mismo. Pero a su vez hemos comentado que una cadena es una matriz de caracteres (un array). Y eso es un tipo complejo, que en este caso se denominan colecciones.

Array o matrices

Un array o matriz es una colección de elementos almacenados en una sucesión. Por ejemplo, una serie de números, o una serie de cadenas. Tradicionalmente, cuando se define un array de un tipo, este solo puede contener datos de ese tipo (números, cadenas, objetos…), pero en Swift tenemos la posibilidad de crear estos con diferentes tipos de datos.

Como podemos ver, en las tres primeras líneas usamos la inferencia de tipo, de forma que el compilador, al ver una sucesión de elementos separados por comas y acotados por corchetes, sabe que lo que queremos crear es una colección de tipo array.

Debéis tener cuidado si usáis un playground para probar el código, no olvidéis incluir la instrucción:

Normalmente se sitúa en la parte superior y permite importar las clases del sistema. En caso contrario, matrizMixta dará un error al no cargar los componentes necesarios para crear arrays con datos de diferentes tipos. No obstante, si accedemos a las propiedades de matrizMixta comprobaremos que el sistema ha empleado “el truco” de transformar todos los datos en objetos del tipo NSObject, la clase superior del sistema para estos.[/box]

También es factible tipificar el tipo de array que queremos crear, como en el caso de la variable matrizCadenaTipificada, donde hemos usado el tipo [String] para indicar que es un tipo cadena indicando dicho tipo acotado entre dos corchetes [], que indica que hablamos de una matriz. Para acceder posteriormente a un valor de la misma, solo hay que indicar el nombre y poner el índice o posición al que queremos acceder entre corchetes, por ejemplo, matrizMixta[2] para acceder a la posición 2 (la tercera en orden).

Como vemos en el ejemplo, usamos la instrucción de impresión en el terminal print para mostrar el valor que está en la posición 2 del array matrizCadenas, de forma que la salida que obtendríamos para dicha instrucción sería:

Como hemos indicado, la posición 2 no es la segunda: es la tercera. Esto es debido a que todos los índices en Swift, al igual que en C o en Objective-C, comienzan por el 0 y no por el 1. Es importante recordar este hecho.

Si queremos cambiar un valor de un array, solo hay que hacer una asignación teniendo presente el índice.

Pero en este caso, nos encontramos un problema. matrizMixta nos da un error al querer asignarle un nuevo valor. ¿Por qué? Porque dicho array está definido como constante (con let) por lo que sus componentes no son mutables o modificables. Por lo tanto, vamos a la definición que hicimos de matrizMixta y cambiamos el let por un var.

De esta forma, ahora la nueva asignación ya no dará error. Hemos de recordar que si creamos un objeto como constante (let) sí podremos modificar sus propiedades (si creamos un botón podremos modificar su color o tamaño, por ejemplo), pero en el caso de diccionarios y arrays, como su contenido no son propiedades de él, si no su propio contenido o valor, no podremos modificarlo si lo definimos como let.

A la hora de añadir valores a un array o incluso sustituir y añadir a la vez, tenemos varias opciones interesantes. Para ello, vamos a usar el operador de agregación += que permite añadir elementos a un array o sumar a una variable un valor u otra variable. En realidad, este operador, suma el array que ya tenemos con uno nuevo, motivo por el que aunque sea un solo valor, hemos de ponerlo entre corchetes.

Vamos a ver un ejemplo donde en el comentario sobre cada línea específica qué se va a realizar.

Finalmente, nuestro array tendría los siguientes valores:

Por último, aunque más adelante lo veremos en mayor detenimiento, podemos usar también rangos para acceder o sustituir valores. Por ejemplo, imaginad que queremos cambiar los valores segundo y tercero a la vez (las posiciones 1 y 2). Podemos usar los rangos, un número de inicio y un número de fin separados por 2 puntos y un símbolo menor o 3 puntos. Estos rangos nos permiten indicar que queremos acceder desde el primer valor del rango hasta el anterior al último o hasta el último inclusive. El rango ..< indica desde el valor de inicio hasta el final sin incluir este y ... el rango completo. Veámoslo en ejemplos:

Es importante notar que cualquier variable queda modificada a la izquierda del = siendo todo lo que hay a la derecha el valor antes de ser modificado. Por eso, las posiciones 7 y 6 son las anteriores a querer cambiar o si hacemos a = a + 1, siendo a igual 2, a la derecha del igual a sigue siendo 2 y a la izquierda, será 3.

Nuestro array ahora quedaría con los siguientes valores:

Los rangos se usan también para la enumeración de arrays a través de bucles (recorrer todos sus elementos o parte), pero eso lo veremos más adelante en otra lección.

En contra de los tipos básicos, los arrays SÍ pueden definirse vacíos. Realmente, no están vacíos pues se inicializan con la estructura, y por eso realmente no están vacíos y podemos crearlos en este estado. La forma de definirlos es usando el doble paréntesis de instancia vacía () y (muy importante) tipificando el dato, por ejemplo, var arrayVacio = [String](). También podemos hacerlo indicando el tipo de dato en formato de primitiva del lenguaje como var arrayVacio = Array<String>().[/box]

Diccionarios

Debido a los cambios efectuados en cuanto a los valores nil en Swift, a partir de la beta 5 de Swift 1, los valores de diccionarios se definen automáticamente como opcionales y requieren un unwrap para extraer su valor. Para entender mejor cómo funcionan los opcionales, echad un vistazo a la lección 2 del curso donde hablamos de ellos

Los diccionarios son algo parecido a un array pero en vez de tener un valor y un auto-índice que nos permita acceder a sus valores, con los diccionarios nosotros asignamos el valor por el que podremos acceder a los mismos. El contenido de cada posición del diccionario puede ser del tipo que queramos, bien datos básicos, bien datos complejos (como un array u otro diccionario) e incluso datos mucho más complejos como objetos, imágenes o bloques de código.

En Swift, además, podemos usar cualquier tipo de dato básico también para el dato de índice. Pero estos índices, como es lógico, han de ser únicos para cada valor de un diccionario. No pueden usarse índices duplicados.

Tanto en los diccionarios, como en los array, podremos guardar casi cualquier tipo de datos básico, complejo o del tipo que queramos siempre que pueda asignarse a una variable, incluso instanciaciones de una clase (cosa que veremos más adelante, vayamos poco a poco). En cuanto al índice del diccionario, solo pueden usarse tipos básicos, conocidos técnicamente como hashable.

La forma de definir una pareja de clave y dato para un diccionario (que iría en una posición del mismo) es usando el separador : para tipificar índice y valor. Imaginemos que queremos guardar un diccionario con el número de películas que se han hecho de cada vengador. En el caso de Iron Man estableceríamos su clave y su valor con "Iron Man":3. Puestos en una sucesión separados por comas, definimos todos los elementos que necesitemos y podemos asignarlos.

Como hemos inferido el tipo (no lo hemos indicado), hemos de tener en cuenta que el compilador habrá creado un diccionario con el tipo [String:Int]. Si quisiéramos tipificar el diccionario, forzando los tipos de datos, lo que haremos será usar la estructura que hemos indicado: Dentro de los corchetes, el primer valor es el tipo usado para el índice, seguido de dos puntos y el tipo de dato que vamos a guardar. No hace falta indicar nada más pues [Clave:Valor] será interpretado por el compilador como Dictionary<Key,Value>.

La forma de modificar o añadir valores a un diccionario es parecida a los array aunque indicando el valor del índice. Simplemente hacemos referencia a la clave que sustituir o añadir y le asignamos un valor. Si existe, será sustituida y si no existe se añadirá al diccionario. En el caso que queramos enumerar o recorrer todos los valores de un diccionario (que veremos más adelante) los valores aparecerán por orden de inserción, como si fuera un array.

Al igual que los array, los diccionarios también pueden inicializarse vacíos y también hay que tipificar los datos siempre, no puede usarse la inferencia. Solo hemos de crear la variable, tipificarla y dejarla vacía, como por ejemplo var dicVacio = [String:Int](). También puede indicarse una capacidad mínima del mismo para reservar la memoria a la hora de inicializar. Por ejemplo: var dicVacio = [String:Int] (minimumCapacity: 3). Esto indica que nuestro diccionario se asignará con una capacidad mínima de 3 valores.[/box]

Mutabilidad e inmutabilidad

Para cerrar esta primera lección, vamos a repasar un concepto para que lo podamos tener bien claro: el concepto de la mutabilidad (variable que puede ser modificada) y la inmutabilidad (que no puede ser modificada). Como ya dijimos al comienzo, los tipos de propiedades pueden ser variables o constantes. Si declaramos un diccionario como constante (con let), este será inmutable e intentar modificar un valor del mismo o añadir valores dará errores de compilación. Igual con un array, cuyos valores podremos modificar, borrar elementos o añadirlos a nuestros antojo si es variable (definido con var), pero no podremos hacer nada si es constante.

Como es obvio, si definimos un diccionario como inmutable, hemos de cargar sus valores en el momento de definirlo pues ya no podremos hacerlo después. Como poder, podríamos definirlo vacío si queremos, pero así se quedaría durante todo el programa sin posibilidad de hacer nada más con él.

Aquí es importante que aprendamos un primer concepto sobre variables por valor o por referencia. Las clases, que son un tipo de dato objeto que veremos más adelante, son valores por referencia. De forma que cuando la asignamos a un let lo que tiene este es simplemente la dirección de memoria donde está dicha clase u objeto. Obviamente, ese valor no podrá cambiarse pero el objeto sí es mutable. No hemos de entender que una clase puede modificarse, porque lo que va en el let es solo la dirección donde está: por eso podemos modificarlo.

Del mismo modo, hemos dicho que todas las variables han de estar inicializadas con un valor, pero en el caso de los let podemos definirlos después.

Para esto hemos de tipificar el tipo de dato y tener presente que no podremos usar o acceder en modo alguno la constante hasta que esta tenga un valor, pero podemos diferir su inicialización si nos conviene en un momento determinado.

Resumen

Haciendo repaso de la lección podemos ver los siguientes conceptos que hemos aprendido.

  • var nos permite definir variables que pueden modificar su valor.
  • let nos define constantes que no pueden modificar su valor.
  • Tipos de variables básicas: String, Int, Double, Float, Bool
  • Tipos de variables complejas (colecciones): Arrays o matrices y diccionarios.
  • Definimos un array: let array=["Hola","Que","Tal"]
  • Definimos un arras tipificado (de Strings): var arrayStringVacio = [String]()
  • Modificamos un array: array[2]="Pasa"
  • Añadimos elementos: array += ["Contigo"]
  • Definimos un diccionario: var diccionario = ["Saludo": "Ola k Ase", "Tontería": 9]
  • Definimos un diccionario vacío (tipificado índice Int contenido String): var dicVacio = [Int:String]()
  • Modificamos un valor de un diccionario: diccionario["Saludo"] = "Bo que pasa"[/box]

En esta lección hemos aprendido cuáles son y cómo funcionan las propiedades, variables, constantes, inferencia, tipos de datos complejos como las colecciones y cómo trabajar con ellos. En la próxima veremos todo lo relacionado con los bucles, la enumeración de datos y formas más complejas de inicializar algunos de los tipos que hemos visto hoy.

Y recordad, si tenéis alguna duda o problema, no tenéis más que escribirnos al formulario de contacto y estaremos encantados de atender vuestras dudas o peticiones de cosas que queráis que veamos específicamente en lecciones del curso, trucos, reseñas… Gracias por estar ahí y buena codificación. 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

Close
Close

Bloqueador de publicidad detectado

Apple Coding hace un uso responsable no invasivo de la publicidad. Considere desactivar su bloqueador para nosotros y así nos ayudará a mejorar día a día. Gracias.