Xebia Blog

En av nackdelarna med att använda segues i storyboards är att du ofta måste skriva kod för att överföra data från källvideokontrollanten till målvideokontrollanten. Metoden prepareForSegue(_:sender:) är rätt ställe att göra detta på. Ibland måste du manuellt utlösa en segue genom att kalla performSegueWithIdentifier(_:sender:), och det är där du vanligtvis vet vilka data du behöver överföra. Hur kan vi undvika att lägga till extra tillståndsvariabler i vår källvycontroller bara för att överföra data? Ett enkelt knep är att använda avsändarparametern som båda metoderna har.

Uppdatering:
Tänk på att detta anses vara ett anti-mönster som kommenterats av några läsare nedan, det här inlägget är tänkt att utforska möjligheterna med segues, vilket inte betyder att du alltid ska använda det. Använd det endast när det är lämpligt eller när inget annat alternativ finns tillgängligt.

Sändarparametern används normalt av storyboards för att ange det UI-element som utlöste seguet, t.ex. en UIB-knapp när den trycks ned eller en UITableViewCell som utlöser seguet genom att välja den. Detta gör det möjligt att bestämma vad som utlöste segue i prepareForSegue:sender:, och baserat på detta (och naturligtvis segue-identifieraren) vidta vissa åtgärder och konfigurera målvyns styrenhet, eller till och med bestämma att den inte ska utföra segue överhuvudtaget genom att returnera false i shouldPerformSegueWithIdentifier(_:sender:).

När det inte är möjligt att utlösa segue från ett UI-element i Storyboard måste du istället använda performSegueWithIdentifier(_:sender:) för att utlösa den manuellt. Detta kan hända när ingen direkt användarinteraktion ska utlösa åtgärden för en kontroll som skapats i kod. Du kanske vill utföra ytterligare logik när du trycker på en knapp och därefter utföra segue. Oavsett hur situationen ser ut kan du använda avsändarargumentet till din fördel. Du kan skicka in vad du än behöver i prepareForSegue(_:sender:) eller shouldPerformSegueWithIdentifier(_:sender:).

Låt oss ta en titt på några exempel.

Screen Shot 2015-05-08 at 23.25.37

Här har vi två mycket enkla view controllers. Den första har tre knappar för olika färger. När man trycker på någon av knapparna kommer namnet på den valda färgen att sättas på en etikett och det kommer att trycka på den andra viewcontrollern. Den tryckta visningskontrollanten kommer att ställa in sin bakgrundsfärg till den färg som representeras av den tryckta knappen. För att göra det måste vi skicka ett UIColor-objekt till målvyns kontrollant.

Även om detta skulle kunna hanteras genom att skapa tre olika segues från knapparna direkt till målvyns kontrollant, valde vi att hantera knapptryckningen själva och utlösa segue manuellt.

Du kan komma fram till något som liknar följande kod för att åstadkomma detta:

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

}

klass ColorViewController: UIViewController {

var color: UIColor?

override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = color
}

}

Vi har skapat en tillståndsvariabel som heter tappedColor för att hålla reda på vilken färg som behöver skickas vidare. Den sätts i var och en av handlingsmetoderna innan vi anropar performSegueWithIdentifier(”ShowColor”, sender: sender) och läses sedan igen i prepareForSegue(_:sender:) så att vi kan skicka den vidare till målvyns styrenhet.

Handlingsmetoderna kommer att ha den tappade UIButtons inställd som avsändarargument, och eftersom det är det faktiska elementet som initierade handlingen, är det vettigt att ställa in det som avsändare när vi utför segue. Så det är vad vi gör i ovanstående kod. Men eftersom vi faktiskt inte använder avsändaren när vi förbereder segue, kan vi lika gärna överföra färgen direkt i stället. Här är en ny version av ViewController som gör exakt 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
}
}
}

}

Detta gör att vi kan bli av med vår extra tappedColor-variabel.

Det kan tyckas (och kanske gör det) att avsändarparametern missbrukas, så använd den med försiktighet och endast där det är lämpligt. Var medveten om konsekvenserna; om någon annan kod eller något element i en Storyboard utlöser samma segue (dvs. med samma identifierare) kan avsändaren bara vara ett UI-element i stället för det objekt du förväntade dig, vilket leder till oväntade resultat och kanske till och med till krascher när du tvångsdefinierar avsändaren till något som den inte är.

Du hittar exempelkoden i form av ett Xcode-projekt på https://github.com/lammertw/SegueColorSample.

Vill du veta mer om det här ämnet?
Kolla på våra konsulttjänster, utbildningserbjudanden och karriärer nedan eller kontakta oss på [email protected]

.

Lämna ett svar

Din e-postadress kommer inte publiceras.