¿Qué encontrarás en este post?
ToggleUna de mis características favoritas de Swift: las extensiones
Llamarme friki, pero siempre que he tenido la posibilidad de trabajar con algún lenguaje de programación el tiempo suficiente como para “más o menos” (seguramente menos que más) conocerlo, he encontrado características del mismo que he valorado por encima del resto.
¡Dar la cara! ¿También os ha pasado, verdad?
Hoy os quiero hablar de una de mis características favoritas de Swift: las extensiones (o extension si hablamos a nivel de lenguaje).
Las extensiones en Swift nos proporcionan la capacidad de ampliar la funcionalidad de una clase, estructura, enumeración o protocolo. No poseen nombre, y nos permiten de forma transparente y mágica, extender, valga la redundancia, funcionalidad de tipos a los que tenemos o NO tenemos acceso (¡ahí lo dejo!).
Siguiendo la propia documentación de swift.org, las extensiones nos permiten:
- Añadir propiedades de instancia calculadas y de tipo computadas.
- Definir funciones de instancia y de tipo.
- Crear nuevos inicializadores.
- Definir subscripts.
- Definir y utilizar nuevos tipos anidados.
- Hacer que un tipo existente se ajuste a un protocolo.
(¡flipa con las extensiones!)
No sé si ha quedado clara la potencia de esta característica y lo mucho que me gusta.
Cómo siempre, lo mejor es verlo en un ejemplo.
Para ello, vamos a usar extensiones para modificar gráficamente y animar UIButton en Swfit 4.
Creando el proyecto
Para llevar a cabo el ejemplo, he creado un proyecto en blanco en Xcode al que he llamado ButtonEffectsExtension.
Tendremos en cuenta que este ejercicio lo he realizado en Xcode 9.4 con Swfit 4.1 e iOS 11.4. De todas formas, no hay ningún problema en realizarlo o ejecutarlo en Xcode 10, Swift 4.2 e iOS 12.
Como ya he comentado, vamos a utilizar extensiones para ampliar las características que nos da por defecto el componente nativo de UIKit que representa un botón, es decir, UIButton.
En nuestro caso, estas características que añadiremos pasarán por poder modificar a nivel visual y animar nuestro botón, de formas que por defecto UIButton no nos permite de forma automática.
Creando la extensión
Si aún no os he convencido de las ventajas de las extensiones, vamos a crear una para ver si así lo consigo.
Para ello, únicamente tendremos que crear un fichero y darle el nombre que más nos guste (recordar que una extensión no tiene un nombre significativo). En mi caso, nombro a los ficheros de extensión con el componente que voy a extender y la palabra “Extension”. Ya que vamos a crear una extensión de UIButton, he llamado al fichero “UIButtonExtension.swift”.
¿Qué contendrá nuestro fichero?
Para crear una extensión de UIBUtton (lo mismo con cualquier tipo de componente) simplemente tendremos que situar el siguiente bloque de código en nuestro fichero:
extension UIButton { }
¡Ya está!
A partir de este momento, todas las operaciones incluidas dentro de este bloque de código pasarán a estar disponibles como funcionalidades nativas del UIButton… Como si Apple decidiera añadirlas dentro de su framework… ¡Magic!
Añadiendo funcionalidades
Ya tenemos creada nuestra extensión, así que vamos a darle funcionalidad.
Lo primero que haremos es crear una función que sirva para redondear los bordes de nuestro UIButton. En mi caso la he llamado round(), tiene la siguiente pinta:
func round() { layer.cornerRadius = bounds.height / 2 clipsToBounds = true }
Hay que tener en cuenta que una extensión nos sitúa dentro del scope del componente a modificar. Esto quiere decir que, al extender nuestro UIButton, podemos acceder a todas sus propiedades directamente, otra forma de explicarlo, es que “self” será el propio UIButton.
De esta manera vemos que accedo directamente a propiedades de un botón (en realidad de un UIView) como su layer, bounds o clipToBounds.
Probando nuestra extensión
Para probar nuestra extensión, he añadido un botón en el ViewController por defecto creado en nuestro Main.storyboard. El botón se vería de la siguiente manera:
Asociamos nuestro botón de la vista al controlador asociado y le ponemos el nombre de “button1”, también creamos un action para recoger la acción del pulsación del mismo. Nuestro ViewController quedaría de la siguiente manera:
final class ViewController: UIViewController { @IBOutlet weak var button1: UIButton! override func viewDidLoad() { super.viewDidLoad() } @IBAction func button1Action(_ sender: Any) { } }
Solo nos quedaría aplicar nuestra extensión. En el “viewDidLoad” accedemos a nuestro “button1” y según escribimos un punto “.”, veremos que tenemos acceso a la función “round()” añadida en nuestra extensión.
De forma automática, y en cualquier parte de nuestro código, podremos aplicar este comportamiento, el cuál por defecto no posee un UIButton.
Al igual que hicimos con el primer botón, vamos a crear 2 más para seguir practicando extensiones.
Para que veáis lo fácil que es reutilizar extensiones, si hacemos “round()”en nuestros nuevos “button2” y “button3”, con una sola instrucción modificaremos visualmente nuestros botones.
Tener en cuenta que esto es un ejemplo muy sencillo (la función “round() únicamente tine 2 líneas”), pensar que si nuestra función tuviese 50 líneas, sería igual de fácil aplicarla.
¿Qué quiere decir esto?
Que si tenemos 100 botones en nuestra app que tienen que seguir la misma guía de estilo, solo con aplicar la propiedad encargada de customizarlos de nuestra extensión será suficiente para mantenerlos uniformes.
¿Qué pasa si el día de mañana desde diseño nos piden cambiar el botón por defecto?
Que únicamente tocando la función de nuestra extensión, todos los botones de la app aplicarán esa modificación visual. Esta misma máxima se aplica también a una funcionalidad concreta o a un error en código. Todo estará centrado en un único punto.
Añadiendo animaciones
Al igual que hemos creado una función para modificar visualmente nuestro botón, vamos a añadir un nuevo comportamiento, esta vez, centrado en animaciones.
Sin más palabrería, vamos a crear funciones que doten a nuestro UIButton con la capacidad de rebotar, brillar y saltar.
Para ello, únicamente volveremos a nuestra extensión y crearemos las siguientes funciones igual que hicimos con “round()”:
/ Rebota func bounce() { UIView.animate(withDuration: 0.1, animations: { self.transform = CGAffineTransform(scaleX: 1.1, y: 1.1) }) { (completion) in UIView.animate(withDuration: 0.1, animations: { self.transform = .identity }) } } // Brilla func shine() { UIView.animate(withDuration: 0.1, animations: { self.alpha = 0.5 }) { (completion) in UIView.animate(withDuration: 0.1, animations: { self.alpha = 1 }) } } // Salta func jump() { UIView.animate(withDuration: 0.1, animations: { self.transform = CGAffineTransform(translationX: 0, y: -10) }) { (completion) in UIView.animate(withDuration: 0.1, animations: { self.transform = .identity }) } }
Tomar notas
Probando animaciones
Para probar estas nuevas funcionalidades de nuestra extensión en forma de animación, utilizaremos las operaciones “Action” asociadas a cada uno de nuestro 3 botones en su ViewController. En el momento que pulsemos un botón, se ejecutará su función “Action” y ahí aprovecharemos para animarlo.
El botón 1 rebotará, el 2 brillará y el 3 saltará. Algo así:
@IBAction func button1Action(_ sender: Any) { button1.bounce() } @IBAction func button2Action(_ sender: Any) { button2.shine() } @IBAction func button3Action(_ sender: Any) { button3.jump() }
Comprobaremos que, al pulsarlo, cada botón se comporta de forma diferente.
Hasta aquí una de las posibles aplicaciones de las extensiones. Por último, mencionar que en nuestra app podemos tener todos los bloques “extension” que queramos aplicados a un mismo componente. Cada una de las funcionalidades añadidas en esos bloques serán incluidas directamente en el componente base.
Espero haberos convencido de los beneficios de las extensiones. Potencia, limpieza, reutilización, rapidez y organización de código en muy pocas líneas.
Podéis ver el desarrollo de este artículo en forma de 2 videotutoriales en mi canal de YouTube “MoureDev by Brais Moure”.
También podéis descargar el proyecto completo en GitHub: https://github.com/mouredev/SwiftUIButtonExtension
Si quieres saber más sobre las extensiones de Swift, esta es su documentación oficial: https://docs.swift.org/swift-book/LanguageGuide/Extensions.html
Muchas gracias por vuestro tiempo.
¡Hasta otra Hackermen!