Xebia Blog

Una de las desventajas de usar segues en los storyboards es que a menudo todavía necesitas escribir código para pasar datos desde el controlador de vista de origen al controlador de vista de destino. El método prepareForSegue(_:sender:) es el lugar adecuado para hacerlo. A veces es necesario desencadenar manualmente un segue llamando a performSegueWithIdentifier(_:sender:), y es ahí donde se suele saber qué datos hay que pasar. ¿Cómo podemos evitar añadir variables de estado adicionales en nuestro controlador de vista de origen sólo para pasar datos? Un truco sencillo es utilizar el parámetro sender que tienen ambos métodos.

Actualización:
Por favor, ten en cuenta que esto se considera un anti-patrón como comentan algunos lectores más abajo, este post pretende explorar las posibilidades de los segues, lo que no significa que debas utilizarlo siempre. Utilízalo sólo cuando sea apropiado o cuando no haya otra opción disponible.

El parámetro sender es normalmente utilizado por los storyboards para indicar el elemento UI que desencadenó el segue, por ejemplo un UIButton al ser presionado o un UITableViewCell que desencadena el segue al seleccionarlo. Esto permite determinar lo que desencadenó el segue en prepareForSegue:sender:, y en base a eso (y por supuesto el identificador del segue) tomar algunas acciones y configurar el controlador de la vista de destino, o incluso determinar que no debe realizar el segue en absoluto devolviendo false en shouldPerformSegueWithIdentifier(_:sender:).

Cuando no es posible desencadenar el segmento desde un elemento de la interfaz de usuario en el guión gráfico, es necesario utilizar performSegueWithIdentifier(_:sender:) para desencadenarlo manualmente. Esto puede ocurrir cuando ninguna interacción directa del usuario debe desencadenar la acción de algún control creado en código. Quizás quieras ejecutar alguna lógica adicional al pulsar un botón y después realizar el segue. Cualquiera que sea la situación, puedes utilizar el argumento sender en tu beneficio. Puedes pasar lo que necesites en prepareForSegue(_:sender:) o shouldPerformSegueWithIdentifier(_:sender:).

Veamos algunos ejemplos.

Screen Shot 2015-05-08 at 23.25.37

Aquí tenemos dos controladores de vista muy simples. El primero tiene tres botones de diferentes colores. Al tocar en cualquiera de los botones, el nombre del color seleccionado se pondrá en una etiqueta y empujará el segundo controlador de vista. El controlador de vista empujado establecerá su color de fondo al color representado por el botón pulsado. Para ello, tenemos que pasar un objeto UIColor al controlador de vista de destino.

Aunque esto podría ser manejado mediante la creación de 3 segues distintos de los botones directamente al controlador de vista de destino, optamos por manejar el toque del botón nosotros mismos y el gatillo el segue manualmente.

Usted podría llegar a algo como el siguiente código para lograr esto:

class ViewController: UIViewController {

@IBOutlet weak var label: UILabel!

var tappedColor: UIColor?

@IBAction func tappedRed(sender: AnyObject) {
label.text = «Tapped Red»
tappedColor = UIColor.redColor()
performSegueWithIdentifier(«ShowColor», sender: sender)
}

@IBAction func tappedGreen(sender: AnyObject) {
label.text = «Tapped Green»
tappedColor = UIColor.greenColor()
performSegueWithIdentifier(«ShowColor», sender: sender)
}

@IBAction func tappedBlue(sender: AnyObject) {
label.text = «Tapped Blue»
tappedColor = UIColor.blueColor()
performSegueWithIdentifier(«ShowColor», sender: sender)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == «ShowColor» {
if let colorViewController = segue.destinationViewController as? ColorViewController {
colorViewController.color = tappedColor
}
}

}

class ColorViewController: UIViewController {

var color: UIColor?

override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = color
}

}

Creamos una variable de estado llamada tappedColor para llevar la cuenta del color que hay que pasar. Se establece en cada uno de los métodos de acción antes de llamar a performSegueWithIdentifier(«ShowColor», sender: sender) y luego se lee de nuevo en prepareForSegue(_:sender:) para que podamos pasarlo al controlador de la vista de destino.

Los métodos de acción tendrán los UIButtons tocados establecidos como el argumento del remitente, y como ese es el elemento real que inició la acción, tiene sentido establecerlo como el remitente al realizar el segue. Así que eso es lo que hacemos en el código anterior. Pero como en realidad no usamos el emisor cuando preparamos el segue, podríamos pasar el color directamente en su lugar. Aquí tenemos una nueva versión del ViewController que hace exactamente eso:

class ViewController: UIViewController {

@IBOutlet weak var label: UILabel!

@IBAction func tappedRed(sender: AnyObject) {
label.text = «Tapped Red»
performSegueWithIdentifier(«ShowColor», sender: UIColor.redColor())
}

@IBAction func tappedGreen(sender: AnyObject) {
label.text = «Tapped Green»
performSegueWithIdentifier(«ShowColor», sender: UIColor.greenColor())
}

@IBAction func tappedBlue(sender: AnyObject) {
label.text = «Tapped Blue»
performSegueWithIdentifier(«ShowColor», sender: UIColor.blueColor())
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == «ShowColor» {
if let colorViewController = segue.destinationViewController as? ColorViewController {
colorViewController.color = sender as? UIColor
}
}
}

}

Esto nos permite deshacernos de nuestra variable extra tappedColor.

Sin embargo, podría parecer (y quizás lo sea) que se abusa del parámetro sender, así que úsalo con cuidado y sólo cuando sea apropiado. Tenga en cuenta las consecuencias; si algún otro código o algún elemento en un Storyboard desencadena el mismo segmento (es decir, con el mismo identificador), entonces el remitente podría ser simplemente un elemento de la interfaz de usuario en lugar del objeto que usted esperaba, lo que conducirá a resultados inesperados y tal vez incluso se bloquea cuando se fuerza el reparto del remitente a algo que no es.

Puedes encontrar el código de ejemplo en forma de proyecto de Xcode en https://github.com/lammertw/SegueColorSample.

¿Quieres saber más sobre este tema?
Mira nuestros servicios de consultoría, ofertas de formación y carreras a continuación o ponte en contacto con nosotros en [email protected]

Deja una respuesta

Tu dirección de correo electrónico no será publicada.