Home » Cursos » Swift 2, Lección 1, variables, constantes, inferencia y colecciones
Curso Swift Lección 1

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"

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.

  • Pingback: Introducción: Indicaciones del curso de Swift | AppleCoding()

  • Pingback: Swift: Extendiendo la funcionalidad de String | AppleCoding()

  • Pingback: Apple cambia Swift en sus últimas betas | AppleCoding()

  • Hola intente hacer:

    vengadores[1…2] = [“Nick Furia”, “Coulson”]
    vengadores[4..<8] = ["Thor", "Viuda Negra", "Hulk", "Ojo de Halcón"]

    y me salió un error del siguiente tipo:

    fatal error: Array replace: subRange extends past the end
    (lldb)

    podrían apoyarme para saber que puede ser? de rrepente la version del xcode

    • Julio César Fernández

      Hola kumikosSantiago,

      Es cierto. En la nueva beta 3 este código da un error y no lo habíamos detectado porque el PlayGround no lo da directamente si no en el terminal. Anteriormente a los cambios en la beta 3, Swift permitía añadir elementos a un array a través de los operadores de rango, de forma que si teníamos 6 elementos y poníamos un rango superior que no existía, él creaba estos nuevos elementos. Al cambiar los conceptos de mutabilidad y hacer más seguro el código, ahora esto no está permitido y por eso obtienes este error.

      He modificado la lección para corregir el problema y ahora todo funciona. Perdona el problema y gracias por avisarnos. Nos alegra que veáis problemas o dudas y aviséis.

      Un saludo,

  • Pingback: Curso de Swift (II), controles de flujo (y opcionales) | AppleCoding()

  • Víctor Rodríguez Martín

    Hola:

    He ejecutado el código:

    var vengadoresMovies: [String:Int] = [“Iron Man”: 3, “Capitán América”: 2, “Hulk”: 2, “Thor”: 2]
    let valorS = vengadoresMovies[“Iron Man”]
    println (“El valor de Iron Man es (valorS)”)

    y me da una cosa extraña:

    El valor de Iron Man es Optional(3)

    Me pasa simpre que uso un diccionario: siempre sale “Optional(valor)” en vez de sólo el valor.

    Saludos de Víctor.-

    • Julio César Fernández

      Hola Victor,

      Debido a los últimos cambios en Swift, los valores de los diccionarios se han tipificado como opcionales para así poder contemplar la posibilidad que estos puedan ser nil. Al contrario que en Objective-C donde nil es nada, en Swift nil está tipificado como la ausencia de valor (siendo de por sí un valor). Por esto, ahora todos los valores en diccionarios se declaran automáticamente como opcionales y en el caso que muestras el Int sería declarado internamente como Int?.

      Si te fijas en el valor de la fila let valorS = vengadoresMovies[“Iron Man”], verás que pone {Some:3}. Esto indica que el valor 3 está en un contenedor opcional y que para extraer el valor hay que descodificarlo (hacerle un unwrap). Tienes varias formas de arreglar esto. La más simple es usar la admiración en la línea de impresión:
      println (“El valor de Iron Man es (valorS!)”)

      O también puedes hacer el unwrap al asignar la variable en el let:
      let valorS = vengadoresMovies[“Iron Man”]!

      Espero haberte aclarado la duda y en breve actualizaremos el post. Gracias por tu comentario y pregunta, así como el aviso.

      Un saludo

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

  • Pingback: Swift Lesson 3: Classes, methods, structs and heritage | Dinesh Ram Kali.()

  • Pingback: Truco de Swift: convertir valores a cadena | Apple Coding()

  • Excelente tutorial. Sin lugar a dudas es lo más didáctico y completo que vi en la web.
    Felicitaciones y espero con ansias más y más capítulos de este curso.
    Saludos!!

    • Julio César Fernández

      Muchas gracias @emiliosmole. Estamos preparando mucho más contenido, entre ellos las siguientes lecciones. Muy pronto.

      Un saludo y gracias por tu positivo comentario. Estas cosas son las que animan a seguir.

  • Pedro A. Gordillo

    Hola Julio César,

    Primero de todo felicitarte por el curso, de lo mejor que encontrado para comenzar en la programación. Muy claro y con ejemplos para poder practicar.

    En el apartado Diccionarios, cuando escribo:

    var vengadoresMovies:[String:Int] =
    [“Iron Man”: 3, “Capitán América”: 2, “Hulk”: 2, “Thor”: 2]

    me aparece una alerta de “Invalid redeclaration”, ¿cómo podría solucionarlo? y ¿a que se debe este error? para tenerlo en cuenta.

    Gracias de antemano,
    Saludos!!

    • Julio César Fernández

      Hola Pedro,
      El error se debe a que ya has usado vengadoresMovies previamente a esa línea con un var o un let usando otro tipo diferente. Cuando se declara un variable usando las palabras clave var o let, no se puede volver a hacer esa instrucción con el mismo nombre.
      Un saludo y me alegro mucho que el curso te guste. Se intenta que sea accesible y fácil de comprender y me alegra ver que lo consigo.
      Julio

  • .[Roberto Hevens]

    Julio:

    Excelente tus conceptos escritos para enseñar la lección. Felicitaciones!

    Un Saludo.

    • Muchas gracias Roberto. Intento hacerlo fácil de entender, y los súper héroes también ponen su parte 🙂 .
      Un saludo

  • Alex Mena

    Excelente lección muy util, y tengo una pregunta, su libro también se puede adquirir en formato físico?

    • Julio César Fernández

      Hola Alex,

      Nos alegramos que te haya sido útil la lección. Respecto al libro, por ahora, no está en formato físico. A partir de septiembre nos planteamos editarlo físicamente, pero por ahora solo puede conseguirse en electrónico.

      Un saludo,

    • Julio César Fernández

      Hola Alex,

      Por ahora no. A partir de otoño habrá una edición física que contemple Swift 2.0.

      Un saludo y nos alegra que te haya sido útil la lección,