Home » Análisis » Análisis Swift 2.2, su primera versión oficial Open Source
Banner Análisis Swift 2.2

Análisis Swift 2.2, su primera versión oficial Open Source

Ayer, con el evento “Let Us Loop You In” de presentación de los nuevos iPhone SE y iPad Pro de 9’7″, Apple también lanzó las versiones finales de las últimas revisiones de sus sistemas operativos: iOS, OS X, watchOS y tvOS. Todas cargadas de novedades, aunque lo más importante es que también sacó Xcode 7.3. Y con esta versión, llega al público general (y en consecuencia a la App Store) la primera versión del lenguaje Swift que ve la luz desde que este es de código abierto.

Y sin duda, los cambios han sido muy importantes, porque estamos hablando que nada menos que 212 personas que no trabajan en Apple han aportado al proyecto en el desarrollo de corrección de errores, propuestas, nuevas funcionalidades, depuraciones y cambios en el lenguaje. En cuanto al uso en sí, pocos cambios que afecten a nuestro trabajo en el día a día, pero sí se han realizado muchas tareas de mejora del lenguaje y pasos esenciales para la próxima gran iteración, Swift 3.0.

Cambios en Swift 2.2

Permitir como etiquetas de argumentos cualquier palabra clave (o casi)

Es habitual encontrarse que muchas veces la mejor forma de etiquetar parámetros en una función es con una palabra clave como in, protocol o defer. Para permitir esta posibilidad, ahora el lenguaje deja usar como nombres de los parámetros cualquiera de estas palabras, a excepción de inout, var o let, por estructura de las propias cabeceras.

De esta forma, si queremos tener un parámetro que se llame protocol, porque nos pueda interesar, pondríamos algo así:

Ojo al detalle dentro de la función. Mientras sí podemos poner el parámetro tal cual como argumento en la cabecera de la función, para hacer referencia al mismo en el código tendremos que poner la descripción entre apóstrofes invertidos, con el objetivo de distinguirlo de la propia palabra dentro del contexto del lenguaje.

Operadores de comparación en tuplas

Hasta ahora, las tuplas no soportaban comparación alguna. Teníamos que descomponer el tipo de dato para poder comparar cada uno de sus componentes por separado. Ahora, sin embargo, se han incorporado al lenguaje los operadores de comparación menor, mayor, menor o igual que y mayor o igual que, así como las de igualación y diferencia.

Internamente, la forma de compararlas es por niveles. Si queremos evaluar si a es menor que b y el componente .0 de a es igual al componente .0 de b, entonces se pasará a verificar el componente .1 de ambos a y b. En el momento que .0 de a sea menor de .0 de b (como es el ejemplo expuesto) el resultado siempre será que a es menor que b. Pero en el caso de c comparado a b, como sus componentes .0 son 5, el sistema pasaría a comprobar el siguiente elemento de la tupla, el componente .1 y en este caso nos diría que b es menor que c porque en el primero es 8 y el siguiente 9.

Nueva palabra clave associatedtype

Un typealias nos permite crear alias a un tipo, de forma que podemos definir un nombre alternativo para un tipo existente. Pero también sirve para crear tipos asociados, es decir, un nombre vacío o placeholder para un tipo usado como parte de un protocolo. Y esto supone un problema conceptual pues no es totalmente correcto usar la misma palabra y se crea confusión al respecto. Por este motivo, se ha creado una nueva palabra clave denominada associatedtype.

Por lo tanto, cuando intentemos crear un typealias dentro de un protocolo nos dará un error y nos dirá que hemos de usar el nuevo associatedtype, lo que permite que se aplican de forma correcta los diferentes conceptos y se entiende que dos cosas distintas.

Llamar a las funciones con su lista de parámetros de forma genérica

Imaginemos que tenemos una clase con 3 versiones diferentes de una misma función, donde el segundo parámetro tiene diferente nombre para permitirnos distinguir más fácilmente a qué estamos llamando. Si esa clase tiene una instancia y desde esa instancia queremos guardar la función en una variable, hasta ahora lo teníamos bastante difícil porque no podíamos especificar de forma alguna qué versión de la función queríamos guardar en una variable o constante.

Siempre podíamos usar la tipificación en la variable destino para evitar la ambigüedad a la hora de llamar a la función, pero había casos donde ni eso nos era útil.

¿Cómo haríamos para guardar en una constante o variable una instancia de la función insertarDato que sea la versión con el parámetro String de nombre cadena? Tendríamos que crear un closure que llamara a la función, lo cual era un poco redundante y un parche para conseguir una funcionalidad no nativa.

Pues bien, ahora no es necesario porque podemos usar los propios nombres de los parámetros y su nomenclatura. De forma que podemos especificar de una forma genérica cuál es el nombre del parámetro y por lo tanto, evitar la ambigüedad a la hora de invocar a una función concreta.

Separados por : podemos hacer una llamada tipo placeholder que hace que _:cadena: sea equivalente a una tipificación que corresponde con la cabecera func insertarDato(index:Int, cadena:String) y con esto solucionar el problema fácilmente.

Nuevo método Selector

Uno de los mayores problemas que tiene Swift a nivel de seguridad, es el hecho que los selectores, ese tipo heredado de Objective-C que almacena la referencia al nombre de un método, se usan con cadenas de texto. No tiene sentido alguno que cuando creamos uno de estos elementos, lo hagamos pasándole una cadena, lo que no permite validar correctamente en forma alguna que dicha referencia pueda existir o no, lo que lleva implícito el consiguiente fallo grave de aplicación.

Y para eso, ahora se ha creado una directiva #selector que sustituye a la anterior forma (bueno, en realidad la antigua puede seguir usándose, pero obviamente es menos recomendada), que permite llamar directamente a cualquier método de una clase desde su propia definición sin tener que acudir a su instanciación.

Para invocar estos nuevos selectores usamos las llamadas nativas de funciones con parámetros que hemos visto en el apartado anterior con la llamada #selector.

Imaginemos que tenemos una clase botón que tiene un control de cuando ha sido tocado, pero queremos que esta invoque un método de la clase padre que lo contiene. Básicamente, un botón de un juego que es un SKSpriteNode donde creamos una clase que hereda de este, captura su propia pulsación e invoca un método. Normalmente, meteríamos el nombre de la función que queremos invocar en el padre (por ejemplo pulsoBoton) y haríamos lo siguiente:

De esta forma, le estamos diciendo a nuestra clase que ejecute la función pulsoBoton del padre de nuestra propia clase, que en este caso será la escena donde se ha añadido dicho SKSpriteNode a través de un addChild. Pero el valor pulsoBoton es una cadena de texto: no hay forma de validar que su referencia sea correcta.

De esta nueva forma podemos, bien enviar como parámetro una instancia de la propia función como hemos visto en el apartado anterior, o directamente llamar a la clase que siempre contendrá los botones, que sabemos es GameScene. Por lo tanto, haríamos esto:

Estamos haciendo referencia al método directamente desde la especificación de la clase, sin que tengamos una instancia. Y en este caso, funcionará sin problema porque nuestro parent es una instancia (objeto) de la clase gameScene. Sin duda, mucho más seguro porque obviamente nunca nos dejará invocar a métodos a través de un selector que no existan.

Control de versiones del lenguaje

Una de las novedades más interesantes, y que forman parte de un adelanto del futuro Swift 3.0 con especificaciones retro-compatibles entre versiones, es la directiva de compilación #if para el lenguaje. Podemos hacer que un código solo se ejecute en caso que la versión de Swift que estemos intentando compilar sea la indicada, con comparación incluida.

Como vemos, el código en el #else ni siquiera será evaluado en caso que nuestro programa esté intentando ser compilado en la versión 2.2.

Conclusiones

Por último, hay un pequeño cambio en AnySequence donde se han incorporado más restricciones de definición con el fin de poder delegar sobre la secuencia debajo del propio tipo, cosa que ahora no podía hacerse anteriormente y obligaba a buscar una forma alternativa demasiado compleja.

A estas importantes mejoras hay que añadir otras que ya comentamos en su momento como que ahora el ++ o el -- tienen una advertencia del compilador que avisa de su eliminación en la versión 3.0, así como el uso de la currificación que también está deprecado en favor del uso de funciones parcializadas puras, más efectivas dentro del lenguaje. Podéis echarle un vistazo a alguno de estos cambios en el análisis que publicamos hace unas semanas.

Solo queda recordar que estos cambios ya los tenéis disponibles en la versión 7.3 de Xcode, la cual también permite hacer playgrounds interactivos como vimos en el mencionado análisis donde adelantamos algunos cambios de Swift 2.2, y que contiene nuevas e interesantes formas de realizar documentación enriquecida. Pero eso lo veremos en un próximo análisis. Hasta entonces, probad, no dejéis de investigar y Good Apple Coding.

P.D. – Comienza la cuenta atrás para la actualización gratuita a Swift 2.2 de “Aprendiendo Swift 2”. Os seguiremos informando.

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 4 Cambios

Los cambios en Swift 4 que harán tu código incompatible: 3 por ahora

El cambio de versión de Swift 3 a 4 es algo que provoca miedos e inseguridades. La memoria del pesado cambio a la versión 3 nos trae malos recuerdos, pero nada más lejos de la realidad en este caso. A fecha 31 de mayo, solo 3 cosas harán nuestro código incompatible. Descúbrelas en este análisis y cuales serán las simples soluciones en caso que esto nos afecte.

  • Eduardo González Joyanes

    Buena entrada en el post… felicidades 😉

  • Marc Lande

    Fantástico! Muchas gracias por mantenernos siempre actualizados!