Conoceremos todas las novedades que introduce Apple en Swift 2 con sencillos ejemplos
Swift 2
El pasado mes de Junio durante el transcurso de la World Wide Developer Conference 2015 Apple presentó su nueva versión del lenguaje Swift, Swift 2. Parece que como ya se presagiaba por el éxito que tuvo su primera versión, Swift es un lenguaje que viene para quedarse y sustituir al anciano Objective-C.
Ahora que ya esta entre nosotros Xcode 7, en este artículo vamos a abordar las que para mi criterio son las novedades mas destacadas, aunque según vayamos trabajando con ello, seguramente descubriremos otros muchos cambios menores, que nos facilitarán nuestro día a día.
Open Source
Una de las grandes sorpresas que desveló Apple en el anuncio de Swift 2, es su carácter Open Source. Esto va a permitir que otros sistemas operativos creen compiladores del lenguaje y puedan utilizar para crear aplicaciones. ¿Significa esto que podremos hacer apps para iOS en Windows? ¿Qué clase de pregunta es esa? ¿Quién querría algo así? ;·)
Cambios importantes que debemos conocer
Con la llegada de Swift 2 deberemos desaprender algunas cosas que hasta ahora hacíamos de una manera, y que a partir de ahora haremos de otra. Esto es algo, que aunque puede enfadar a muchos programadores, hay que entender la inmadurez que tiene a día de hoy el lenguaje, y que Apple se va adaptando a las novedades que incorpora y muchas veces a lo que escucha de la propia comunidad.
Vamos a ver cuales son esos cambios que debemos conocer.
Desaparece println
Y es que amigos, println
desaparece, y a partir de ahora print
hace su papel. Hasta ahora si queríamos imprimir por consola algo con un salto de carro, utilizábamos println
, y si lo queríamos imprimir sin salto de carro, utilizábamos print
. Programadores iOS cambiando el código de su app en 3, 2, 1…
Alertas para el uso de var y let
A partir de ahora cuando definamos una variable con var
, Xcode nos mostrará un warning hasta que no compruebe que efectivamente vamos a variar su contenido. Este aviso nos indicará que dicha variable no ha sido modificada en el código y que por tanto deberíamos estar haciendo uso de constantes con let
.
Ocurrirá lo mismo con aquellas constantes y/o variables que definamos y luego no usemos en nuestro código, las cuales tendrán en Xcode un warning a su lado indicando este hecho.
Repeat While
La sentencia de control do-while
pasa a ser repeat-while
, ya que la cláusula do
pasa a utilizarse para el control de errores como veremos mas adelante.
1 2 3 4 5 6 7 8 |
var cont = 0 repeat { cont++ print(cont) } while cont < 5 |
Cambios en String
La forma de interactuar con algunos de los métodos de cadenas han variado con Swift 2.
La clase String
deja de conformar el protocolo CollectionType
y por tanto ya no es posible gestionarla como una colección de caracteres. Ahora cuenta con una propiedad characters
, que nos va a facilitar la vista a dicha colección, que nos va a permitir acceder a dicha colección para iterar la cadena como un array de caracteres, o para obtener otra información como su longitud con el método count
.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Definimos una cadena sencilla let myString = "Miguel" // Obtenemos el numero total de caracteres de la cadena let totalCharacters = myString.characters.count // Recorremos los caracteres de la cadena for character in myString.characters { print(character) } |
Los enums ahora pueden pintarse por consola mostrando su valor en lugar de enum value.
Seguro que muchos de vosotros habéis utilizado en vuestro código enumeraciones para crear conjuntos de valores que poder utilizar como parámetros, un catalogo de posibles errores, etc. Pues bien, a la hora de imprimir el valor de una variable que contiene un enum nos encontrábamos con el problema de que en consola únicamente veíamos el texto enum value. Pues esto se acabó, ahora si pintamos por consola un enum, veremos su valor.
1 2 3 4 5 6 7 8 9 10 |
enum Moneda { case Cara case Cruz } let monedaTirada = Moneda.Cruz print(monedaTirada) // Mostrará por consola el texto "Cruz" |
Nuevas funcionalidades
Además de los cambios anteriormente descritos, Swift 2 incluye algunas novedades que van a enriquecer considerablemente el lenguaje.
Try / Catch para control de errores
En ocasiones las cosas fallan y debemos ser capaces de capturar dichos errores y entender qué los ha producido. Swift en su primer versión carecía de un modelo de control de errores, y es en Swift 2 donde se solventa este problema, con el uso do
try
catch
.
La sintaxis es bien sencilla:
1 2 3 4 5 6 7 8 |
do { let users = try getUsersFromDatabase() } catch { print("Se ha producido un error al recuperar usuarios de base de datos") } |
Dentro del bloque do
en aquellos puntos donde invoquemos a funciones o métodos que implementen o lancen errores, utilizaremos como prefijo la palabra reservada try
. Al final del do
tendremos un bloque catch
donde podremos hacer un tratamiento específico para cada uno de los errores que puedan darse.
Cuando queramos que un método nuestro lance errores que deban ser gestionados por quien nos invoca, basta con utilizar esta sintaxis:
1 2 3 4 5 6 7 |
func getUsersFromDatabase() throws -> [User] { // Aquí se produce un problema y queremos levantar el error throw Errors.DataBaseError } |
En primer lugar la cláusula throws
le indica a Swift que nuestro método lanza errores que deben ser gestionados por quien nos invoque. En segundo lugar, la utilización de throw
en aquellos puntos del método donde se produzcan errores, nos permite lanzar dicha excepción/error. Es importante saber que el error que levantemos deberá conformar el protocolo ErrorType
, en nuestro caso una enumeración que definiríamos como se indica a continuación:
1 2 3 4 5 6 7 |
enum Errors : ErrorType { case DataBaseError case WrongValueError } |
La cláusula guard
La cláusula guard
nos permite, normalmente al inicio de un método o bloque de código, controlar que no estemos ante un escenario erróneo donde no deba ejecutarse nuestro código, por variables que no tenga valor, u otros condicionantes que deban hacer que nuestro código avise a quien nos invoca comunicándole el error inesperado que se ha producido.
De algún modo, la sentencia guard
tiene un cierto parecido con assert
, y difiere de un clásico if-else
, en que lo que se va a indicar en la condición es lo que debería pasar. Vamos a verlo con un ejemplo.
Si nosotros quisiéramos que la ejecución de código no continuara si x
tuviera un valor inferior a 0, haríamos lo siguiente:
1 2 3 4 5 6 |
if (x < 0) { throw Errors.WrongValueError } |
Si os fijáis, lo que estamos comprobando con nuestro if
es justamente la condición que queremos que no ocurra.
Con la sentencia guard
nuestro código quedaría de la siguiente forma:
1 2 3 4 5 6 |
guard x >= 0 else { throw Errors.WrongValueError } |
Aunque parece lo mismo, y de hecho hace lo mismo, para la lectura del código es mas claro encontrarnos con guard
, que sería algo como «garantizame que …».
Si estamos trabajando con un valor opcional, anteriormente haríamos:
1 2 3 4 5 6 |
if (x == nil || x < 0) { throw Errors.WrongValueError } |
Y con la nueva sintaxis haríamos:
1 2 3 4 5 6 |
guard let x = x where x > 0 else { throw Errors.WrongValueError } |
De nuevo la condición por la que preguntamos, es la que se debe cumplir, lo que da una claridad a nuestro código que antes no teníamos para este tipo de comprobaciones.
Defer para cosas que queramos que siempre se ejecuten
Otra maravilla que nos encontramos en Swift 2 es la posibilidad de definir un bloque de código que siempre se ejecute dentro de un método, independientemente de que se produzcan errores a lanzar. defer
nos permite definir un bloque de código que siempre se va a ejecutar antes de abandonarse el método, sea cual sea el motivo por el que se abandona.
La sintaxis es muy sencilla:
1 2 3 4 5 6 |
defer { // Cerrar sesión con base de datos } |
La unión de guard
, defer
y la nueva gestión de errores con do
, try
y catch
puede ser una combinación explosiva para securizar nuestro código.
Utilización de where en sentencias de control
En el ejemplo que os mostraba anteriormente para explicar el uso de guard
habréis observado que en la condición se incluye también la cláusula where
. Pues bien, en Swift 2 se incluye algo muy interesante, y es el uso de where
para filtrar sentencias de control. Vamos a verlo con un ejemplo.
Hasta ahora si queríamos iterar una colección y en caso de que el objeto iterado tuviera una característica se ejecutara un código concreto haríamos lo siguiente:
1 2 3 4 5 6 7 8 |
for persona in personas { if persona.nombre == "Miguel" { print("Encontrada: \(persona.nombre)") } } |
Pues con el uso de la cláusula where
podemos simplificar estas dos sentencias en una sola de la siguiente forma:
1 2 3 4 5 6 |
for persona in personas where persona.nombre == "Miguel" { print("Encontrada: \(persona.nombre)") } |
De esta forma no solo mejoramos la claridad de nuestro código sino que ademas logramos optimizar a nivel rendimiento la ejecución de nuestra iteración.
Disponibilidad de API
Swift 2 nos trae una forma rápida y sencilla de detectar la versión de iOS que esta utilizando nuestro usuario, para de esa forma poder hacer uso de unas u otras apis y funcionalidad en nuestro código.
Hasta ahora la forma mas segura de hacer esto mismo, era minar nuestro código de comprobaciones sobre la existencia de una clase, o confirmar que una clase responde a un selector (método) determinado.
Sin embargo ahora podemos hacer estas comprobaciones directamente en base a la versión de iOS, y que un determinado código solo se ejecute en dicha versión.
La sintaxis es muy sencilla como vemos a continuación:
1 2 3 4 5 6 7 8 |
if #available(iOS 9, *) { // Nuestro código para iOS 9 } else { // Nuestro código para versiones anteriores } |
De nuevo, como en otras muchas funcionalidades introducidas en esta nueva versión del lenguaje, mejoramos la claridad de nuestro código enormemente.
Extendiendo la funcionalidad de un protocolo
En esta nueva versión del lenguaje Swift, se incorporan los protocolos a la lista de clases que pueden ser extendidas mediante el uso extensiones. Al igual que haríamos para extender una clase, podemos extender la funcionalidad de un protocolo:
1 2 3 4 5 6 |
extension MyProtocol { } |
El gran valor añadido que tiene la extensión de protocolos, es que podemos incorporar lógica que deseemos a objetos, de los cuales desconocemos su clase, pero si sabemos que conforman un protocolo dado. Con ello se abre un horizonte de posibilidades, dando capacidades al lenguaje que antes ni soñábamos.
Conclusión
En conclusión Swift 2 trae consigo algunos incomodos cambios que nos obligarán a refactorizar parte de nuestro código, pero sin duda tras ese esfuerzo inicial, contamos con un lenguaje más sólido, más versátil y con una sintaxis que va mejorando su claridad por momentos.
Excelente artículo que resume algunas de las cosas nuevas.
Ya era justo que regresaras 😛 Aunque ya era parte de Swift, Seria bueno un chapter sobre las nuevas formas de iteracion sobre las colleciones como:
(- .filter,
– .map
– .reduce)
Asi como algo muy importante. Closures
Saludos
Hola Manuel,
Ya tenía ganas yo también de volver a escribir! ;·)
La tematica que comentas estaría bien, pero efectivamente todas esas funcionalidades (filter, map y reduce) ya estaban en Swift 1.0.
De todos modos, tendré en cuenta tu comentario para próximos artículos, puedes estar seguro.
Un placer volver a estar por aquí compartiendo lo que aprendo.
Un abrazo.