Home » Swift » Swift 3, novedades en la librería de Foundation
Banner Foundation

Swift 3, novedades en la librería de Foundation

El gran cambio en Swift 3, que supone (entre otros) modificaciones en la nomenclatura de muchas clases, es debido en gran medida a una necesaria adaptación de la librería Foundation del mismo. La misma librería donde los objetos y valores básicos que nos permiten trabajar con el lenguaje están contenidos. Dentro del contexto de una aplicación Swift, podemos elegir usar cualquier API de las que pertenecen a Cocoa, como UIKit, Core Data o cualquier otra, pero la librería Foundation siempre está presente por encima de todas estas.

207_whats_new_in_foundation_for_swift

El verdadero corazón de Swift es esta librería, y su objetivo es poder expresar en el lenguaje aquellas intenciones que tengamos a la hora de crear un programa, de una forma clara y lógica. Una forma que garantice una experiencia consistente. Igualmente se persigue una experiencia que pueda ser usada en otros sistemas. Y para conseguir esto el hecho que la SDK de Cocoa esté o no presente para crear programas en Swift para cualquier plataforma es un reto a superar que ha requerido cambios.

Por lo tanto, tipos que hasta ahora formaban parte de Cocoa, ahora han pasado a formar parte del propio Swift con el objeto que, cuando no esté Cocoa en otras plataformas, el lenguaje siga teniendo la consistencia necesaria para poder trabajar con él. Y también, no hay que olvidar que Swift no está fuertemente orientado a objetos como Objective-C si no que tiene una potente orientación a tipos por valor. Por lo tanto, se requerían realizar cambios profundos para despegar Cocoa y la herencia de Objective-C y conseguir una entidad propia en Swift.

Ejemplos de cambios

Algunos de los tipos que ahora forman parte de Swift nativamente y que, además, se han incorporado como tipos por valor (y no por referencia) son: AffineTransform, CharacterSet, Data, Date, DateComponents, IndexPath, IndexSet, Notification, URL, URLComponents o UUID. Y de hecho, algunos de ellos han cambiado en la nomenclatura pues, por ejemplo, Data equivale al antiguo NSData que ahora ya no existe en Swift 3. Porque como ya dijimos, todos los prefijos NS han sido eliminados de la especificación de Swift 3.

Estos que hemos mencionado (entre otros) no solo son tipos nuevos dentro del lenguaje y ya no son objetos, si no que además incorporan más funciones que lo que tenían en su versión con Cocoa y cambian la forma en que la mutabilidad e inmutabilidad era gestionada cuando eran objetos para el sistema.

Otro de los grandes cambios se debe a la facultad de Swift de soportar enumeraciones anidadas, que permiten crear una clase que dentro tenga valores de enumeración diferentes. Por ejemplo, el antiguo objeto NSNumberFormatter tenía una serie de valores para el formateador como NSNumberFormatterStyle o NSNumberFormatterBehavior. Ahora, con Swift 3, se incluyen todos dentro de una misma clase NumberFormatter con los tipos style o behavior. Mucho más limpio e intuitivo para trabajar.

Otro gran cambio son los singletons, donde invocamos una clase y luego el estado de la misma que la inicializa como un método propio, nos devuelve la instancia de la clase viva del singleton. El ejemplo más claro lo tenemos en NSUserDefaults donde la declaración en Objective-C era de este estilo:

Las adaptaciones de Swift 3 han requerido en muchas ocasiones cambios en Objective-C, con el fin de mantener la compatibilidad y el puente de especificación entre ambos (para que la SDK de Cocoa siga funcionando sin problema). Para adaptar mejor al nuevo Swift, se han introducido las propiedades de clase en Objective-C de forma que los nuevos singletons pueden ser propiedades declaradas de tipo class. La nueva declaración quedaría de la siguiente forma:

Al hacer esto, ahora ya podemos usar una especificación mejor en Swift 3 y mucho más limpia. Pero no solo cuando estemos trabajando con Cocoa, si no que cuando vayamos a otro sistema también seguiremos manteniendo la misma coherencia.

Así, ahora standardUserDefaults ya no será una public class func si no que pasará a ser una public class var. Aplicado además el cambio de nomenclatura en la nueva guía para Swift 3, tendríamos una transformación como vemos en el ejemplo más abajo:

De hecho, cuando hablamos de los cambios de tipos en cuanto al cambio de referencia a valor, también obtenemos optimizaciones muy interesantes que hacen que nuestro código sea mucho más eficiente. Por ejemplo, anteriormente en Swift, suponemos que creamos una función que nos permita saber cuándo salir de casa con un dato de fecha. El tipo NSDate en Swift 2.2 es un objeto, por lo que hay que tener en cuenta la suma de referencias que tendremos en el código al hacer el ejemplo:

En este caso, cuando creamos la constante fecha estamos sumando 1 al contador de referencias del objeto, y posteriormente, al invocar el método, creamos otra nueva. Sin embargo, en Swift 3, las fechas no son objetos y basan su mutabilidad o no en el tipo let o var donde residen directamente. Es decir, como objeto, fecha es solo un puntero y por eso podríamos modificar su valor y siempre tendríamos un dato mutable aunque esté en un let. Pero ahora, en Swift 3, ya no es así. Porque si queremos modificar la fecha, tenemos que poner un var en vez de un let para que pueda ser mutable.

Y gracias a las interfaces fluidas de Swift, podemos concatenar la inicialización y la llamada al método en una sola línea y tener un codificación mucho más óptima, guardada en una constante (más eficiente para la memoria) pero que tenga el procesamiento que necesitamos.

La llamada a salirDeCasa() devolvería por defecto un var que se convertiría en inmutable al meter dicho resultado en un let. Pero en ese estado transitorio cuando ha sido inicializado, la interfaz fluida nos permite concatenar la llamada al método que transforma el resultado inicializado con addingTimeInterval. Al final, dicho valor, es el que acaba en el let liberando de memoria los var creados transitoriamente al momento, ya que el ámbito es el que hay a la derecha del símbolo = que representa la asignación de valor.

Este sería además, uno de los ejemplos de lo que haría el migrador a Swift 3 y de cómo podemos nosotros mejorar dicha migración. El asistente de migración de Swift 3 cogería el código de Swift 2 y lo convertiría automáticamente en la versión “menos” eficiente por la que el let se convierte en var y luego se invoca para crear let recordatorio.

Pero tenemos que pasar porque fecha sea var en dicho caso. Nosotros somos lo que tenemos que (conociendo el lenguaje) saber que la mejor forma de realizar esto es guardarlo directamente en una constante let cuyo valor sea la llamada fluida de la inicialización y su método con la línea let fecha = salirDeCasa().addingTimeInterval(-5.0 * 60.0).

Otras grandes ventajas de estos cambios en Swift 3 es, por ejemplo, la posibilidad de crear timers cuyo código cuando expire sea un closure. Usando los trailing closures (poner el closure como último parámetro) podemos obtener creaciones muy simples de temporizadores como esta.

No necesitamos un parámetro target ni utilizar un selector para decir dónde queremos buscar el código que se ejecute al expirar el temporizador. El código a ejecutar cuando el Timer expira está directamente en el closure y, al ser un dato por valor, en el momento que el temporizador (o el ámbito que lo contiene) muera, este morirá sin problema y saldrá de memoria.

El puente entre Swift y Objective-C

Otro de los grandes cambios, es un nuevo puente entre Cocoa y sus objetos, cuando son invocados desde Swift. Muchos tipos que realizan el tratamiento de objetos propio de Objective-C, ahora usan los nuevos tipos que ya incorporan métodos de copia implícitos al ser tipos por valor. Por ejemplo, un control NSDatePicker que tenga dos valores como un control de fecha, en su puente en Swift 2.2 cambiaría mínimamente pero su resultado sería mucho más eficiente.

Pasamos de tener objetos con la referencia @NSCopying a usar directamente la mutabilidad del var y su facultad de ser un valor por tipo y no por referencia, por lo que al asignarse la copia se hace implícitamente.

Conclusiones

Una de las grandes bases de la guía de diseño de Swift 3, está basada en una máxima: “omitir palabras no necesarias”, por lo tanto lo que tenemos que pensar es que tenemos que huir de las clásicas repeticiones que insisten una y otra vez en la aparición de los mismos términos, tal como sucede en la construcción de mensajes de Objective-C. Ahora, con estos cambios, Swift consigue tener entidad propia y ser un lenguaje independiente y no, como hasta ahora, dependiente de Objective-C en una parte importante. Como ya comentamos en uno de nuestros últimos podcast, es Objective-C el que se está adaptando a Swift y no lo contrario, de forma que podemos ver claro que Swift es el futuro para Apple y puede ser mucho más en otros ecosistemas.

Pero en contra de lo que pueda pensarse, el cambio es sencillo, simple… intuitivo. Al final, muchos de los cambios se han realizado internamente y el propio trabajo o búsqueda de métodos nos va a dar la solución de manera clara e incluso tendremos asistentes de código que nos recomendarán un cambio en la forma de llamar a un método cuando usemos una forma antigua. Con todo estos cambios de objetos por referencia a tipos por valor o el uso extendido de enumeraciones en muchos de los valores o llamadas (incluso enumeraciones que devuelvan diferentes tipos de datos en cada llamada) tenemos una forma mucha más clara de manejar el lenguaje. Y cuando lo conocemos en su raíz, nosotros mismos seremos capaces de optimizar el código y hacerlo más eficiente de lo que el mismo asistente de migración sea capaz.

Conseguimos con todo esto, que Swift sea un lenguaje mucho más concreto, más definido, más fácil a la hora de desarrollar y aprender cómo desarrollar o cómo adaptar nuestro código. Por lo tanto, no pensemos que el cambio será dramático, nada más lejos de la realidad. Será un cambio lógico e intuitivo. Todos estos cambios pueden probarlos ya con Xcode 8 (se puede bajar con una cuenta gratuita de desarrollador). Así que bájenlo, prueben, experimenten y Good Apple Coding.

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

Swift 3.1 Hoja de Ruta

Swift 3.1, hoja de ruta hasta primavera de 2017

Swift 3.1 marca su hoja de ruta de aquí a primavera de 2017 con dos grandes retos: la compatibilidad de código con la versión 3.0 y potenciar el gestor de paquetes y la integración con servidor para conseguir aun más rendimiento en soluciones como Kitura, Vapor o Perfect (entre otros). Descubre los detalles en nuestra noticia y qué nos depara esta nueva versión menor del lenguaje.

  • Eduardo González Joyanes

    Julio, como siempre, fantástico artículo. Felicidades!!!!