Swift: Selector, una forma elegante de usarlo


Swift a diferencia de Objective-C es un lenguaje nuevo y aplicar mejores prácticas a la hora de estar programando a veces resulta ser un poco difícil tener una referencia de cuales son las “best practices” para determinado método; debido a eso actualmente tenemos que hacer mucha experimentación y encontrar las mejores rutas que podemos tomar y adoptar un estilo propio.

Desde que salió Swift he estado trabajando en varios proyectos y he actualizado otros mas en mi rutina diaria. Durante todo este tiempo he aprendido ciertas técnicas que son muy buenas y que se podrían adoptar fácilmente.

Selectors

Antes de Swift 2.2, los selectors se definían mediante un simple string y debido a eso y a que simplemente somos humanos pues era muy fácil equivocarse, no se tenía autocomplete, en tiempo de compilación no nos podíamos dar cuenta y simplemente podía ser un simple error de dedo.

let button = UIButton(type: .System)
button.addTarget(self, action: Selector("buttonPressed:"), forControlEvents: .TouchUpInside)
...
func buttonPressed(sender: UIButton) {}

En el ejemplo anterior podemos ver como se hacía anteriormente y podemos observar ciertas cosas:

  • Es muy bueno tener un naming convention para todas tus funciones una manera que me gusta a mi tener es ponerle la accion en el nombre de la función por ejemplo en este caso es Pressed.
  • Como el Selector tiene un string yo fácilmente puedo poner buttonPresed: y no me marcaría nada en tiempo de compilación por lo que es mas propenso a caer un error de dedo.

Mejoras en Swift 2.2

Ahora con el nuevo release de swift nuestros selectors son mucho mas seguros al utilizar, ahora tenemos un nuevo keyword #selector y nos puede marcar en tiempo de compilación y autocompletar, pero aún siguen siendo un poco dificiles de leer y sinceramente se mira super feo

button.addTarget(self, action: #selector(ViewController.buttonPressed(_:)), forControlEvents: .TouchUpInside)

Como ven al agregar un target a mi botón podemos ver que esta super larga la linea de código. Una manera sencilla de acortar esa línea y que se vea mas leíble podría ser esta:

private struct Action {
static let buttonPressed = #selector(ViewController.buttonPressed(_:))
}
...
button.addTarget(self, action: Action.buttonPressed, forControlEvents: .TouchUpInside)

Eso se ve mucho mejor, con esa estructura podemos poner todos nuestros actions en nuestra estructura y accederlos desde un solo lugar.

Otra cosa que recomiendo es que le pongan el mismo nombre a su constante para que mantengan uniformidad con el método.

La estructura debe de ser private porque no queremos que nos de conflictos de redeclaración de estructura, es decir, si la ponemos private significa que solo esta disponible para el archivo .swift en el que estamos usandolo y eso nos permite volverlo a declarar para cada controlador que ocupemos ademas de tener auto-complete en nuestro archivo de swift.

Esta manera funciona a la perfección pero de verdad hay una mejor manera de hacerlo para que se vea elegante tu código y muy al estilo swift. ¿Por qué en lugar de una estructura no extendemos nuestra clase Selector?

fileprivate extension Selector {
    static let buttonPressed = #selector(ViewController.buttonPressed(_:))
}
...
button.addTarget(self, action: .buttonPressed, forControlEvents: .TouchUpInside)

El benificio de hacer una extension y no una estructura es que tomamos ventaja de la inferencia de tipo de Swift, es decir como action: espera objecto tipo Selector podemos omitir poner Selector. cuando pasamos el valor que queremos, y eso funciona normalmente en las clases que tenemos en swift por ejemplo el estilo de selección de un cell en un tableview:

cell.selectionStyle = .None

Adoptar este tipo de estilo hace nuestro código muy leíble y mejor, si te gustó este artículo por favor no dudes en compartirlo y envíame un tweet para seguir haciendo mas tutoriales en español como este.