Xebia Blog

En af ulemperne ved at bruge segues i storyboards er, at du ofte stadig skal skrive kode til at overføre data fra kildeviewcontrolleren til destinationsviewcontrolleren. Metoden prepareForSegue(_:sender:) er det rette sted at gøre dette. Nogle gange skal du manuelt udløse en segue ved at kalde performSegueWithIdentifier(_:sender:), og det er der, du normalt ved, hvilke data du skal videregive. Hvordan kan vi undgå at tilføje ekstra tilstandsvariabler i vores kildevisningscontroller bare for at videregive data? Et simpelt trick er at bruge afsenderparameteren, som begge metoder har.

Update:
Husk at dette betragtes som et anti-mønster, som kommenteret af nogle læsere nedenfor, dette indlæg er beregnet til at udforske mulighederne for segues, hvilket ikke betyder at du altid skal bruge det. Brug det kun, når det er hensigtsmæssigt, eller når der ikke er andre muligheder.

Afsenderparameteren bruges normalt af storyboards til at angive det UI-element, der udløste seguen, f.eks. en UIButton, når der trykkes på den, eller en UITableViewCell, der udløser seguen ved at vælge den. Dette giver dig mulighed for at bestemme, hvad der udløste seguen i prepareForSegue:sender:, og på baggrund heraf (og naturligvis segue-identifikatoren) foretage nogle handlinger og konfigurere destinationsvisningscontrolleren, eller endda bestemme, at den slet ikke skal udføre seguen ved at returnere false i shouldPerformSegueWithIdentifier(_:sender:).

Når det ikke er muligt at udløse segue fra et UI-element i Storyboardet, skal du i stedet bruge performSegueWithIdentifier(_:sender:) for at udløse den manuelt. Dette kan ske, når ingen direkte brugerinteraktion skal udløse handlingen af en kontrol, der blev oprettet i kode. Måske vil du udføre noget ekstra logik, når du trykker på en knap og derefter udføre segue. Uanset hvad situationen er, kan du bruge afsenderargumentet til din fordel. Du kan sende det, du måtte have brug for, ind i prepareForSegue(_:sender:) eller shouldPerformSegueWithIdentifier(_:sender:).

Lad os se på nogle eksempler.

Skærmoptagelse 2015-05-08 kl. 23.25.37

Her har vi to meget enkle viewcontrollere. Den første har tre knapper til forskellige farver. Når man trykker på en af knapperne, vil navnet på den valgte farve blive sat på en label, og det vil skubbe den anden view controller. Den skubbede view controller vil sætte sin baggrundsfarve til den farve, der er repræsenteret af den trykkede knap. For at gøre det skal vi videregive et UIColor-objekt til målvisningscontrolleren.

Selv om dette kunne håndteres ved at oprette tre forskellige seguer fra knapperne direkte til målvisningscontrolleren, valgte vi at håndtere tryk på knappen selv og udløse seguen manuelt.

Du kan finde på noget i retning af følgende kode for at opnå dette:

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
}

}

Vi har oprettet en tilstandsvariabel kaldet tappedColor for at holde styr på den farve, der skal videregives. Den sættes i hver af handlingsmetoderne, før vi kalder performSegueWithIdentifier(“ShowColor”, sender: sender) og læses derefter igen i prepareForSegue(_:sender:), så vi kan videregive den til destinationsvisningscontrolleren.

Handlingsmetoderne vil have den tappede UIButtons indstillet som afsenderargument, og da det er det faktiske element, der indledte handlingen, giver det mening at indstille det som afsender, når vi udfører seguen. Så det er det, vi gør i ovenstående kode. Men da vi faktisk ikke bruger afsenderen, når vi forbereder seguen, kan vi lige så godt sende farven direkte videre i stedet. Her er en ny version af ViewController, der gør præcis det:

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
}
}
}
}

}

Dette giver os mulighed for at slippe af med vores ekstra tappedColor-variabel.

Det kan dog synes at misbruge (og det gør det måske også) afsenderparameteren, så brug den med forsigtighed og kun hvor det er hensigtsmæssigt. Vær opmærksom på konsekvenserne; hvis en anden kode eller et element i et Storyboard udløser den samme segue (dvs. med samme identifikator), kan afsenderen blot være et UI-element i stedet for det objekt, du forventede, hvilket vil føre til uventede resultater og måske endda til nedbrud, når du tvinger afsenderen til noget, den ikke er.

Du kan finde prøvekoden i form af et Xcode-projekt på https://github.com/lammertw/SegueColorSample.

Vil du vide mere om dette emne?
Kig på vores konsulentydelser, uddannelsestilbud og karrieremuligheder nedenfor eller kontakt os på [email protected]

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.