Programación

Variables, constantes, inferencia y colecciones en Swift 3

Variables y constantes

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.

Las variables se definen con la palabra clave var antecediendo al nombre de la misma y las constantes con la palabra let. Ejemplo:

var saludo = "Hola"

var numero = 5

let cantidad = "20 unidades"

let pedido = 15
Podemos definir varias variables o constantes en una misma línea, separando cada nombre y su valor por una coma.
var x = 0, y = 0.0, z = 0, ax = "Prueba", bx = "Otra prueba"

let a = 3.0, b = 2, c = 3, aa = "Testeo"
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.

var mensaje: String = "Hola ¿qué tal?"

var pi: Double = 3.14159265

var verdad: Bool = true

let veces: Int = 320

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 datosla 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.

Como unir cadenas?

Podemos unir cadenas de estar forma:

var cadena = "hola"

var cadena2 = "que"

var cadena3 = cadena + " " + cadena2

//Tambien podemos interpolar

var numero = 10

var cadena4 = "Numero: \(numero)"

print(cadena4)

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.

var mCadenas = ["Uno","Dos","Tres","Cuatro"]

var mNumeros = [1,2,3,4]

let mCadenaTipificada:[String] = ["Cinco","Seis","Siete"]

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

mNumeros[3] = 7

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.

Otras cosas útiles:

//Para conocer el numero de elementos de un array

mCadenas.count

//Para conocer si el array esta vacio

mCadenas.isEmpty

Por último, podemos usar también rangos para acceder o sustituir valores. Por ejemplo, imaginar 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:

var m = ["Mad Men", "Better Call Saul", "Talking Dead", "Humans"]

m += ["Preacher"]

m += ["The Killing"]

// Sustituimos el rango que va del 1 al 2 con dos nuevos valores

m[1...2] = ["Prison Break", "Breaking Bad"]

// Añadimos dos elementos nuevos

m += ["Lost", "Game Of Thrones"]

// Y ahora cambiamos esos dos últimos elementos

m[4..<8] = ["TWD", "FTWD", m[7], m[6]]

print(m)

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.

Los rangos se usan también para la enumeración de arrays a través de bucles (recorrer todos sus elementos o parte).

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>()

Diccionarios

Los diccionarios 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 series de AMC. En el caso de TWD estableceríamos su clave y su valor con «TWD»:1. Puestos en una sucesión separados por comas, definimos todos los elementos que necesitemos y podemos asignarlos.

var series = ["TWD": 1, "FTWD": 2]

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 guardarNo hace falta indicar nada más pues [Clave:Valor] será interpretado por el compilador como Dictionary<Key,Value>.

var series:[String:Int] = ["TWD": 1, "FTWD": 2]

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.

// Cambiamos el valor de TWD por 3

series["TWD"] = 3

// Como Breaking Bad no existía, se añade con un valor de 0

series["Breaking Bad"] = 0
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.

Mutabilidad e inmutabilidad

Para terminar este artículo, 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.

let test:Int

test = 3
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.
Salir de la versión móvil