Constantes y variables
Cualquier tipo de aplicación necesita poder guardar datos temporalmente en la memoria para poder trabajar con ellos. Las constantes y variables son apartados reservados en la memoria del dispositivo para que podamos acceder a la información que contienen durante la ejecución del programa.
En este sentido, se define una variable como un espacio en memoria que puede ser modificado por un algoritmo y una constante como una zona de memoria de solo lectura, que no puede ser modificada una vez se le haya asignado un valor inicial.
Para poder utilizar tanto las variables como las constantes, debemos definir un nombre descriptivo de su contenido y debemos asociarles además un tipo de dato según la información que vayan a contener.
En Swift, para definir una variable debemos utilizar la palabra reservada var
mientras que para definir una constante, debemos utilizar la palabra reservada let
:
let maxAlumnosGrupo = 30 var numAlumnosGrupo = 26
En el ejemplo anterior estamos declarando una constante con la cantidad máxima de alumnos en una clase. Dado que esa cantidad no variará, es conveniente definirla como una constante. Por otro lado, estamos declarando una variable con la cantidad de alumnos que actualmente se encuentran en la clase, y cuyo valor inicial hemos establecido en 26. Este valor puede ir modificándose a medida que transcurre el tiempo, y por ese motivo debemos utilizar obligatoriamente una variable para guardar este dato.
Hemos mencionado además que las variables y las constantes se asocian a nombres, tipos de datos y valores, pero en el ejemplo anterior sin embargo, no hemos especificado el tipo de dato de la variable o la constante. Esto es posible porque Swift utiliza inferencia de tipos, es decir, que “adivina” el tipo de dato que se quiere guardar en memoria utilizando como referencia el valor que le hayamos asignando inicialmente.
Si observamos el ejemplo anterior, en ambos casos asignamos valores numéricos enteros, por lo tanto Swift infiere que ambos son del tipo Int
.
En cualquier caso, si quisiéramos indicar nosotros mismos el tipo de dato de manera explícita podríamos especificarlo después del nombre de la variable utilizando los dos puntos (:) como separador, tal como se observa en el siguiente ejemplo:
let maxAlumnosGrupo: Int = 30 var numAlumnosGrupo: Int = 26 let nombreProfesorInformatica: String = "Fernando"
En el ejemplo podemos observar que escribimos el nombre de la variable o constante, seguida de dos puntos, el tipo de dato y por último el valor que queramos asignar inicialmente.
Imprimiendo valores
Para imprimir el valor de una constante o una variable en la consola, podemos utilizar la función print(_:separator:terminator:)
:
let nombreProfesorInformatica: String = "Fernando" print(nombreProfesorInformatica) // Imprime: Fernando
La función print
es global y nos permite imprimir uno o más valores. Posee dos parámetros que tienen valores por defecto, los cuales son separator y terminator. Esto implica que al momento de invocar a la función print
, estos parámetros pueden ser omitidos por completo.
En caso de no especificar nada, esta función añade al final un salto de línea. Si se quiere indicar que el cursor se mantenga en la misma línea, se debe pasar un string vacío al parámetro terminator
:
let nombreProfesorInformatica = "Fernando" print(nombreProfesorInformatica, terminator:"") // Imprime: Fernando
Una técnica muy utilizada a la hora de imprimir valores usando print
, es la de interpolación de cadenas. Gracias a ella se puede especificar un espacio dentro de la cadena de texto para que sea reemplazado por el valor de una variable o constante al momento de ejecutarse. Se utiliza una barra invertida y se encierra la variable o constante entre paréntesis:
let maxAlumnosGrupo = 30 var numAlumnosGrupo = 26 print("De \(maxAlumnosGrupo) alumnos matriculados, hoy han venido \(numAlumnosGrupo)") // Imprime: De 30 alumnos matriculados, hoy han venido 26
A diferencia de otros lenguajes, Swift no requiere el uso del punto y coma al finalizar una sentencia. Sin embargo, está permitido su uso:
let nombreProfesorInformatica = "Fernando"; print(nombreProfesorInformatica); // Imprime: Fernando
Comentarios
Es muy común escribir texto dentro del código que no queremos que sea ejecutado pero que nos sirve como anotaciones o recordatorios. Estos comentarios son ignorados por el compilador y no son ejecutados.
Existen dos tipos de comentarios. Por un lado, tenemos a los de línea, quienes comienzan con dos barras o diagonales:
// Esto es un comentario de linea
Por otro lado, tenemos los comentarios multilineas, que se encierran entre /* y */ :
/* Esto es un comentario de varias líneas */
Operadores básicos
Los operadores básicos incluidos en Swift son los siguientes:
- Adición (+)
- Sustracción (-)
- Multiplicación (*)
- División (/)
- Resto (%) –> hace referencia al resto de una división. Ej: 10/3 es igual a 3 y sobra 1. Por lo tanto, el resto es 1.
- Asignación (=) -> Se usa para darle un valor a una variable o constante, como vimos en los ejemplos.
- Igual a (==)
- Distinto a (!=)
- Mayor a (>)
- Menor a (<)
- Mayor o igual (>=)
- Menor o igual (<=)
Tipos de datos
En Swift podemos encontrar los siguientes tipos de dato:
- Números enteros: Int y UInt
- Números de coma flotante: Float y Double
- String y Character
- Bool
- Tuplas
- Tipos de Colección: Array, Set y Dictionary
En este post vamos a ver los usos más comunes de cada uno. Cabe mencionar que los tipos de dato se escriben con Mayúsculas la primer letra.
Números enteros
Los números enteros son aquellos que no poseen parte decimal o fracción, como el 1, 2, 3, 58 y -90. Existen dos tipos:
- Con signo (signed): Son aquellos que pueden ser negativos, cero o positivos. Existen en sus versiones de 8, 16, 32 y 64 bits llamados de la siguiente manera:
- Int8
- Int16
- Int32
- Int64
Asimismo, Swift provee una versión adicional llamada Int
que coincide en tamaño con aquel que posee la misma cantidad de bits que el sistema en donde se está ejecutando. Esto es, si el sistema es de 32 bits, entonces Int
tiene el mismo tamaño que Int32
y, si el sistema es de 64, equivale al Int64
.
- Sin signo (unsigned): Son aquellos que pueden ser cero o positivos. De la misma manera que los anteriores, Swift provee el tipo
UInt
que coincide conUInt32
oUInt64
, dependiendo de la cantidad de bits del sistema. Las otras versiones de 8 y 16 bits también están disponibles.
Si bien ambos tipos están disponibles, es recomendable siempre usar Int
.
let numero1 = 5 print(numero1) // Imprime: 5 let numero2 = numero1 + 6 print(numero2) // Imprime: 11 var numero3:Int32 = 90 numero3 = numero3 + 40 print(numero3) // Imprime: 130
Números de coma flotante
Son aquellos números que poseen parte decimal, como por ejemplo: 3.14 o -45.392607. Existen dos tipos:
- Double: se utiliza para representar un número de coma flotante de 64 bits
- Float: se utiliza para representar un número de coma flotante de 32 bits
El hecho de que Double
sea de 64 bits implica que puede almacenar un mayor rango de valores, con una precisión de al menos 15 decimales, lo que lo hace preferible en cuanto a su uso en casos generales.
String y Character
Un Character
es un carácter cualquiera mientras que un String
es una cadena de texto o bien, una colección de Characters.
Para poder usar un String
, basta con crear una constante o variable y asignarle la cadena de texto que queramos que almacene, encerrado entre comillas dobles:
let texto1 = "Esto es un String"
En algunas implementaciones, es posible necesitar crear un String
vacío inicialmente para luego asignarle un valor más adelante. Para lograr ese comportamiento, se puede utilizar una cadena vacía o usar el inicializador que trae String
:
var textoVacio = "" var textoVacio2 = String() textoVacio = "Hola Mundo!" textoVacio2 = "Hola Mundo!"
Asimismo, se puede modificar una cadena de texto utilizando el operador +=, siempre que la misma esté declarada como una variable:
var textoVacio = "" textoVacio += "Hola Mundo!" textoVacio += " cómo estás?" print(textoVacio) // Imprime: Hola Mundo! cómo estás?
Como dijimos anteriormente, un String
puede verse también como un conjunto de Characters. Por lo tanto, si queremos concatenar un Character
a un String
la operatoria es un poco distinta. Si usamos la técnica anterior la misma no va a funcionar ya que un String
solo puede concatenarse con otro String
. Sin embargo, podemos hacer uso del método append
de String
para agregar el Character en cuestión. Un punto a tener en cuenta es que para usar una variable de este tipo, es necesario especificar el tipo de dato, ya que de lo contrario Swift inferirá que se trata de un String
:
var textoVacio = "" textoVacio += "Hola Mundo! cómo estás?" let exclamacion:Character = "!" textoVacio.append(exclamacion) print(textoVacio) // Imprime: Hola Mundo! cómo estás?!
En el ejemplo, se declara una constante exclamación del tipo Character
y se le asigna un valor. Como se aclaró previamente, es necesario indicarle al compilador que esta constante es del tipo Character
, de lo contrario inferirá que se trata de un String
de un solo carácter.
Por último, Swift incorpora una técnica muy utilizada llamada Interpolación de Cadenas (String interpolation) que permite armar una cadena de texto combinando texto, números, funciones, variables y otras expresiones. Cada ítem a incluir en la cadena debe ser encerrada entre paréntesis y precedida por una barra invertida:
let cadena = "El número \(numero3) es más grande que el número \(numero2)" print(cadena) // Imprime: El número 130 es más grande que el número 11
Como se puede ver en el ejemplo, estamos usando las variables numero2 y numero3 creados anteriormente para armar un texto que los incorpora en un mismo String
resultante. Recordemos que estas variables son del tipo Int
, pero al estar dentro de los paréntesis y la barra, se convierte su tipo o salida a String
y se concatena al resto de la cadena.
Por lo tanto, para concatenar string en Swift tenemos la opción de usar el operador +=, en el cual a una variable String
se le puede adicionar otro a continuación, el operador +, para construir una cadena a partir de otras que se concatenan mediante ese operador, o la interpolación de cadenas, que a su vez nos permite convertir a String
valores de otro tipo de dato e insertarlo dentro de una cadena resultante.
Bool
El tipo de dato booleano permite que una constante o variable pueda valer true
o false
. Son utilizados para tomar decisiones en base a comparaciones lógicas.
let heladeraLlena = false if heladeraLlena { print("A preparar algo para comer!") } else { print("Tenemos que comprar comida") } // Imprime: Tenemos que comprar comida
En el ejemplo anterior, se declara una constante indicando que la heladera no se encuentra llena. Luego se pregunta si la misma está llena, pero al no estarlo se ejecuta solo la sentencia encerrada en el else
.
Tuplas
Las tuplas permiten agrupar varios valores de cualquier tipo en uno solo.
let ubicacion = (-34.599722, -58.381944) print("Buenos Aires se encuentra en la longitud \(ubicacion.0)") // Imprime: Buenos Aires se encuentra en la longitud -34.599722
En el ejemplo anterior, declaramos una tupla del tipo (Double, Double)
con las coordenadas de longitud y latitud de la provincia de Buenos Aires. Luego, usamos la longitud haciendo referencia a ella por su posición en la Tupla (el cual empieza por el índice 0) y se imprime su valor dentro de un String
más grande usando la técnica de String Interpolation.
Un punto a tener en cuenta es que las tuplas pueden contener cualquier cantidad de elementos y los mismos pueden ser a su vez de distintos tipos, como por ejemplo:
- (Int, Int)
- (Int, String)
- (Bool, String, Int)
- (Double, Float, Bool, String, Int)
Otra forma de acceder a los valores que contiene la tupla es mediante el nomenclado de sus elementos. De esta manera, al ponerle un nombre a cada uno, simplemente hacemos referencia a ellos por este atributo:
let registro = (nombre: "Fernando", esMayorDeEdad: true) if registro.esMayorDeEdad { print("\(registro.nombre) está autorizado a ingresar al club") } // Imrpime: Fernando está autorizado a ingresar al club
En este caso, para poder hacer uso de los datos de la tupla registro, simplemente hacemos referencia a los nombres de sus elementos.
Las tuplas son especialmente útiles cuando se utilizan como valores de retorno en funciones, ya que les da la posibilidad de devolver más de un valor al mismo tiempo.
Tipos de colección
Existen tres tipos de colecciones en Swift: los arrays son colecciones ordenadas de elementos, los Sets son colecciones sin ordenar y con valores únicos y por ultimo, los Diccionarios son listas sin ordenar de elementos clave-valor.
Todos los tipos de colección son claros en cuanto al tipo de dato que almacenan. Esto significa que una vez declaradas las colecciones, solo se podrán agregar elementos del mismo tipo de dato de los que fueron indicados al principio. Por lo tanto, si se dispone de un array de Strings, solo se podrá agregarle Strings y no números enteros o booleanos.
Arrays
Se trata de colecciones ordenadas de elementos, los cuales pueden aparecer más de una vez dentro del array. Como es una lista ordenada, cada elemento ocupa una posición indicado por un índice que comienza con 0. Por lo tanto, el primer elemento ocupa la posición 0, el segundo la posición 1, etcétera.
Para crear un array, se puede inferir su tipo de acuerdo a los datos iniciales que se le asigna (encerrados entre corchetes) o bien, se puede crear un array vacío usando un inicializador al cual se le debe indicar el tipo de dato:
let array1 = ["uno", "dos", "tres"] print("El primer elemento del array es \(array1.first!)") // Imprime: El primer elemento del array es uno var array2 = [Int]() array2.append(1) array2.append(4) array2.append(9) print("El segundo elemento del array2 es \(array2[1])") // Imprime: El segundo elemento del array2 es 4
En el primer ejemplo, se infiere que el arreglo será un array de Strings. En cambio en el segundo se crea inicialmente un array de enteros vacío y luego se le agregan 3 datos. Un punto a tener en cuenta es que si queremos ver el primer elemento podemos usar el subíndice 0 o el método first
(al cual le agregamos un signo de exclamación por tratarse de un opcional, lo que veremos más tarde). Si queremos ver el segundo elemento, debemos usar el subíndice 1, como se ve en el segundo ejemplo.
Para eliminar un elemento del array, se utiliza el método remove(at:)
y se indica el subíndice:
array2.remove(at: 1) print("El segundo elemento del array2 es \(array2[1])") // Imprime: El segundo elemento del array2 es 9
Al eliminar el segundo elemento del array, luego su lugar es ocupado por el numero 9 que anteriormente ocupaba el tercer lugar.
Sets
Se trata de un tipo de colección de elementos que no siguen un orden y que solo aparecen una vez dentro de la colección. Es útil cuando justamente el orden no es importante o bien, cuando se requiere asegurar que el listado contenga valores únicos.
De la misma manera que los arrays, podemos crear Sets asignándoles valores al momento de declararlos por primera vez o bien, usar inicializadores para crearlos vacíos:
let coleccion = Set<Int>() print("Tenemos \(coleccion.count) elementos") // Imprime: Tenemos 0 elementos var nombres:Set<String> = ["Juan", "Luis"]
Un punto a tener en cuenta es que si se quiere usar un Set
inicializándolo pasándole los datos que va a contener (segundo ejemplo) es necesario indicar el tipo de dato del mismo ya que Swift no puede inferir si se trata de un Set o de un Array. En el ejemplo, se indicó el tipo de dato Set
.
Para insertar un valor en la colección se utiliza el método insert(_:)
y para eliminar remove(_:)
:
var alumnos:Set<String> = ["Juan", "Luis"] nombres.insert("Pedro") nombres.insert("Javier") for dato in nombres { print("\(dato)") } // Imprime: // Juan // Luis // Pedro // Javier nombres.remove("Pedro") for dato in nombres { print("\(dato)") } // Imprime: // Juan // Luis // Javier
En el ejemplo anterior, usamos el Set
nombres creado previamente y le agregamos dos valores adicionales. Para mostrar el contenido de la colección, usamos un for
para recorrerlo, en donde se crea una constante temporal llamada dato que contiene el valor de cada elemento según la iteración de la que se trate. Es decir, el for
se ejecuta 4 veces y la primera vez que ingresa, la constante dato es igual a “Lionel”. La segunda equivale a “Messi”, y así sucesivamente. Finalmente eliminamos un elemento y volvemos a recorrer la colección para validar.
Diccionarios
Un diccionario permite almacenar asociaciones de pares clave – valor, en donde todas las claves de la colección son del mismo tipo y todos los valores son del mismo tipo pero puede ser distinto que el tipo de la clave. Los elementos aquí guardados no siguen un orden determinado y no pueden repetirse dos elementos con la misma clave.
Se denomina diccionario porque al igual que un diccionario convencional, los valores aquí almacenados son buscados mediante su clave. Es por esto que las claves no pueden repetirse ya que solo se admite devolver un valor al momento de realizar una búsqueda, siempre que la clave exista.
Para poder usar un Diccionario, se debe determinar entre corchetes el par clave – valor, los cuales se separan por dos puntos (:). En el caso de querer indicar el tipo de dato de cada uno de ellos, puede hacerse usando la misma convención.
var monedas: [String:String] = ["ARS":"Peso argentino", "USD": "Dolar americano", "MXN":"Peso Mexicano"]
En este caso, se indicó el tipo de dato [String:String]
de manera explícita pero, al asignarle los valores al momento de declarar la variable monedas, es perfectamente válido omitir el tipo de dato ya que el mismo se puede inferir. Es decir, también pudo haberse escrito así:
var monedas = ["ARS":"Peso argentino", "USD": "Dolar americano", "MXN":"Peso Mexicano"]
Para poder acceder al valor de una determinada clave basta con indicar la misma como si se tratase de un subíndice:
let peso = monedas["ARS"] print("\(peso!)") //Devuelve: //Peso argentino
Si se quiere agregar un nuevo valor, se debe usar la misma técnica vista en el ejemplo anterior pero asignándole un valor:
monedas["CRC"] = "Colones" var colones = monedas["CRC"] print("\(colones!)") //Devuelve: //Colones
Para modificar un valor cuya clave ya existe, se utiliza la misma técnica:
monedas["CRC"] = "Colones Costa Rica" colones = monedas["CRC"] print("\(colones!)") //Devuelve: //Colones Costa Rica
Ejemplo completo
let cantidadMaximaDeJugadoresPorEquipo = 11 var cantidadDeDelanteros = 2 var nombreDeUsuario: String = "Gabriel" let cantidadDeMesesEnUnAño: Int = 12 print(nombreDeUsuario); //Devuelve: //Gabriel print(nombreDeUsuario, terminator:"") //Devuelve: //Gabriel print("De los \(cantidadMaximaDeJugadoresPorEquipo), \(cantidadDeDelanteros) están jugando como delanteros") //Devuelve: //De los 11, 2 están jugando como delanteros //Esto es un comentario de linea /* Esto es un comentario de varias lineas*/ //Números enteros let numero1 = 5 print(numero1) //Devuelve: //5 let numero2 = numero1 + 6 print(numero2) //Devuelve: //11 var numero3:Int32 = 90 numero3 = numero3 + 40 print(numero3) //Devuelve: //130 //Números de coma flotante var numero4:Float = 3.45 //String y Characters let texto1 = "Esto es un String" var textoVacio = "" var textoVacio2 = String() textoVacio = "Hola Mundo!" textoVacio2 = "Hola Mundo!" textoVacio += " cómo están?" print(textoVacio) //Devuelve: //Hola Mundo! cómo están? let exclamacion:Character = "!" textoVacio.append(exclamacion) print(textoVacio) //Devuelve: //Hola Mundo! cómo están?! let cadena = "El número \(numero3) es más grande que el número \(numero2)" print(cadena) //Devuelve: //El número 130 es más grande que el número 11 //Bool let heladeraLlena = false if heladeraLlena { print("A preparar algo para comer!") } else { print("Tenemos que comprar comida :(") } //Devuelve: //Tenemos que comprar comida //Tuples let ubicacion = (-34.599722, -58.381944) print("Buenos Aires se encuentra en la longitud \(ubicacion.0)") //Devuelve: //Buenos Aires se encuentra en la longitud -34.599722 let registro = (nombre: "Gabriel", esMayorDeEdad: true) if registro.esMayorDeEdad { print("\(registro.nombre) está autorizado a ingresar al club") } //Devuelve: //Gabriel está autorizado a ingresar al club //Array let arreglo1 = ["uno", "dos" ,"tres"] print("El primer elemento del arreglo es \(arreglo1.first!)") //Devuelve: //El primer elemento del arreglo es uno var arreglo2 = [Int]() arreglo2.append(1) arreglo2.append(4) arreglo2.append(9) print("El segundo elemento del arreglo2 es \(arreglo2[1])") //Devuelve: //El segundo elemento del arreglo2 es 4 arreglo2.remove(at: 1) print("El segundo elemento del arreglo2 es \(arreglo2[1])") //Devuelve: //El segundo elemento del arreglo2 es 9 //SET let coleccion = Set<Int>() print("Tenemos \(coleccion.count) elementos") //Devuelve: // Tenemos 0 elementos var nombres:Set<String> = ["Lionel","Messi"] nombres.insert("Neymar") nombres.insert("Iniesta") for dato in nombres { print("\(dato)") } //Devuelve: //Lionel //Messi //Neymar //Iniesta nombres.remove("Neymar") for dato in nombres { print("\(dato)") } //Devuelve: //Lionel //Messi //Iniesta var monedas: [String:String] = ["ARS":"Peso argentino", "USD": "Dolar americano", "MXN":"Peso Mexicano"] let peso = monedas["ARS"] print("\(peso!)") //Devuelve: //Peso argentino monedas["CRC"] = "Colones" var colones = monedas["CRC"] print("\(colones!)") //Devuelve: //Colones monedas["CRC"] = "Colones Costa Rica" colones = monedas["CRC"] print("\(colones!)") //Devuelve: //Colones Costa Rica