Xebia Blog

Een van de nadelen van het gebruik van segues in storyboards is dat je vaak nog code moet schrijven om gegevens van de source view controller door te geven aan de destination view controller. De prepareForSegue(_:sender:) methode is de juiste plaats om dit te doen. Soms moet je handmatig een segue triggeren door performSegueWithIdentifier(_:sender:) op te roepen, en daar weet je meestal welke gegevens je moet doorgeven. Hoe kunnen we vermijden dat we extra state variabelen toevoegen in onze source view controller enkel en alleen om data door te geven? Een eenvoudige truc is om de sender parameter te gebruiken die beide methods hebben.

Update:
Bedenk wel dat dit als een anti-pattern wordt beschouwd zoals door sommige lezers hieronder is opgemerkt, deze post is bedoeld om de mogelijkheden van segues te verkennen, wat niet wil zeggen dat je het altijd moet gebruiken. Gebruik het alleen wanneer het gepast is of wanneer er geen andere optie beschikbaar is.

De sender parameter wordt normaal gesproken gebruikt door storyboards om het UI element aan te geven dat de segue heeft getriggerd, bijvoorbeeld een UIButton wanneer deze wordt ingedrukt of een UITableViewCell die de segue triggert door deze te selecteren. Dit stelt je in staat om te bepalen wat de segue triggerde in prepareForSegue:sender:, en op basis daarvan (en natuurlijk de segue identifier) een aantal acties te ondernemen en de destination view controller te configureren, of zelfs te bepalen dat het de segue helemaal niet moet uitvoeren door false terug te geven in shouldPerformSegueWithIdentifier(_:sender:).

Wanneer het niet mogelijk is om de segue te triggeren vanuit een UI element in het Storyboard, moet je performSegueWithIdentifier(_:sender:) gebruiken om het handmatig te triggeren. Dit kan gebeuren wanneer geen directe gebruikersinteractie de actie moet triggeren van een controle die in code is gemaakt. Misschien wil je wat extra logica uitvoeren wanneer je op een knop drukt en daarna de segue uitvoeren. Wat de situatie ook is, je kunt het sender argument in je voordeel gebruiken. Je kunt alles wat je nodig hebt doorgeven in prepareForSegue(_:sender:) of shouldPerformSegueWithIdentifier(_:sender:).

Laten we eens kijken naar een paar voorbeelden.

Screen Shot 2015-05-08 at 23.25.37

Hier hebben we twee heel eenvoudige view controllers. De eerste heeft drie knoppen voor verschillende kleuren. Als je op een van de knoppen tikt, wordt de naam van de geselecteerde kleur op een label gezet en wordt de tweede view controller geduwd. De geduwde view controller zal zijn achtergrondkleur instellen op de kleur die wordt vertegenwoordigd door de getikte knop. Om dat te doen, moeten we een UIColor object doorgeven aan de doel view controller.

Ondanks dat dit zou kunnen worden afgehandeld door 3 verschillende segues te maken van de knoppen direct naar de doel view controller, kozen we ervoor om het aantikken van de knop zelf af te handelen en de segue handmatig te triggeren.

Je zou met iets als de volgende code op de proppen kunnen komen om dit te bereiken:

class ViewController: UIViewController {

@IBOutlet weak var label: UILabel!

var tappedColor: UIColor?

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

@IBAction func tappedGreen(sender: AnyObject) {
label.text = “Getikt Groen”
tappedColor = UIColor.greenColor()
performSegueWithIdentifier(“ShowColor”, sender: sender)
}

@IBAction func tappedBlue(sender: AnyObject) {
label.text = “Getikt Blauw”
tappedColor = UIColor.blueColor()
uitvoerSegueWithIdentifier(“ShowColor”, afzender: afzender)
}

override func prepareForSegue(segue: UIStoryboardSegue, afzender: 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
}

}

We hebben een state variabele aangemaakt, genaamd tappedColor, om bij te houden welke kleur moet worden doorgegeven. Deze wordt in elke actiemethode ingesteld voordat performSegueWithIdentifier(“ShowColor”, afzender: afzender) wordt aangeroepen en vervolgens opnieuw gelezen in prepareForSegue(_:afzender:) zodat we deze kunnen doorgeven aan de bestemmingsviewcontroller.

De actiemethoden hebben de afgetapte UIButtons ingesteld als het afzenderargument, en aangezien dat het eigenlijke element is dat de actie heeft gestart, is het logisch om dat als afzender in te stellen wanneer de segue wordt uitgevoerd. Dus dat is wat we doen in de bovenstaande code. Maar omdat we de afzender niet gebruiken bij het voorbereiden van de segue, kunnen we net zo goed de kleur direct doorgeven. Hier is een nieuwe versie van de ViewController die precies dat doet:

class ViewController: UIViewController {

@IBOutlet weak var label: UILabel!

@IBAction func tappedRed(afzender: AnyObject) {
label.text = “Tapped Red”
performSegueWithIdentifier(“ShowColor”, afzender: UIColor.redColor())
}

@IBAction func tappedGreen(afzender: AnyObject) {
label.text = “Getikt Groen”
uitvoerSegueWithIdentifier(“ShowColor”, afzender: UIColor.greenColor())
}

@IBAction func tappedBlue(afzender: AnyObject) {
label.text = “Getikt Blauw”
uitvoerSegueWithIdentifier(“ShowColor”, afzender: UIColor.blueColor())
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
indien segue.identifier ==”ShowColor” {
indien colorViewController = segue.destinationViewController als? ColorViewController {
colorViewController.color = afzender als? UIColor
}
}
}

}

Dit stelt ons in staat om ons te ontdoen van onze extra tappedColor variabele.

Het lijkt echter (en misschien doet het dat ook) misbruik te maken van de sender parameter, dus gebruik deze voorzichtig en alleen waar nodig. Wees je bewust van de gevolgen; als een andere code of een element in een Storyboard dezelfde segue triggert (dat wil zeggen met dezelfde identifier), dan kan de afzender gewoon een UI-element zijn in plaats van het object dat je verwachtte, wat zal leiden tot onverwachte resultaten en misschien zelfs crashes als je de afzender forceert te casten naar iets wat het niet is.

De voorbeeldcode in de vorm van een Xcode project is te vinden op https://github.com/lammertw/SegueColorSample.

Wilt u meer weten over dit onderwerp?
Kijk hieronder naar onze consultancy diensten, trainingsaanbiedingen en carrières of neem contact met ons op via [email protected]

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.