Saltar al contenido →

SwiftUI & Opaque Result Type

Ayer, durante la Keynote inaugural de la WWDC 2019, se presentó SwiftUI, el nuevo framework para construir interfaces de usuario válidas para todos los dispositivos.

Una de las cosas que me llamó la atención fue que en todos los ejemplos, al construir una View su propiedad body devolvía un tipo View al que le anteponían la palabra reservada some.

En este artículo verás qué es some y para que se usa, pero ya te adelanto que todo tiene que ver con Opaque Return Types.

¿Y qué es eso de los Opaque Return Types?

La propuesta SE-0244 que se ha incorporado a Swift en su versión 5.1 y es basicamente la posibilidad de ocultar el tipo que devuelve la función/propiedad/subscriptor y ofrecer en su lugar un protocolo.

Instead of providing a concrete type as the function’s return type, the return value is described in terms of the protocols it supports

Pero entonces es lo mismo que usar Protocols…

No, no es lo mismo, básicamente porque los Tipos Opacos (Opaque Types) preservan su identidad, es decir, que el compilador sabe a que tipo pertenece, mientras que con los protocolos el compilador sabe que puede ser cualquier tipo que conforme dicho protocolo.

Generally speaking, protocol types give you more flexibility about the underlying types of the values they store, and opaque types let you make stronger guarantees about those underlying types.

Enséñame un ejemplo

Vamos a intentar comparar diferentes dispositivos, concretamente un iPhone y un Mac. A priori lo que tenemos que hacer es que las estructuras que representan a estos dispositivos implementen el protocolo Equatable. Hasta aquí todo correcto.

La fábrica donde se construyen estos dos dispositivos tiene dos funciones que devuelven una nueva instancia de cada uno estos dispositivos. Lo que queremos es comparar dispositivos del mismo modelo para ver si son iguales.

Ahora voy a probar a crear dos Mac y a compararlos. Verás que todo va bien y que los dos son iguales.

Pero qué pasa si en lugar de 2 Mac creo un Mac y un iPhone. A priorí pensarás que compilará bien y luego nos dirá que son diferentes. Pues no.

Obtendremos un error de compilación ya que aunque nosotros veamos que ambas funciones devuelven Equatable el compilar lo que ve es que una devuelve un Mac y la otra un iPhone y ninguna de las extensiones de Equatable cumple con el tipo de comparación que queremos hacer.

El error que nos muestra el compilador es…

Y no, tampoco vale que sobrecargues la función == para que acepte los dos tipos como parámetro.

De esta manera podemos trabajar con la versatilidad que nos dan los protocolos pero sabiendo en todo momento que el compilador nos da su bendición en todas y cada una de las operaciones que hagamos con esos tipos opacos.

¡Espera un momento! Pues que las funciones devuelve sólo Equatable

En principio parece una idea muy buena… hasta que te topas con las constraints que tiene implementadas el protocolo. Vamos, que cambiar some Equatable por Equatable como tipo de datos devuelto sólo nos daría este error del compilador

Que le vamos a hacer… 😉

Enlaces de interés

Publicado en Swift SwiftUI