Jednou z nevýhod používání segmentů ve storyboardech je, že často musíte ještě napsat kód pro předání dat ze zdrojového řadiče zobrazení do cílového řadiče zobrazení. Metoda prepareForSegue(_:sender:) je tím správným místem, kde to lze provést. Někdy je třeba ručně spustit segue voláním metody performSegueWithIdentifier(_:sender:), a právě tam obvykle víte, jaká data je třeba předat. Jak se můžeme vyhnout přidávání dalších stavových proměnných v našem zdrojovém řadiči zobrazení jen kvůli předávání dat? Jednoduchý trik spočívá v použití parametru sender, který mají obě metody.
Aktualizace:
Mějte prosím na paměti, že je to považováno za anti-vzor, jak komentovali někteří čtenáři níže, tento příspěvek je určen k prozkoumání možností segues, což neznamená, že byste ho měli používat vždy. Používejte jej pouze tehdy, když je to vhodné nebo když není k dispozici jiná možnost.
Parametr sender se obvykle používá ve storyboardech k označení prvku uživatelského rozhraní, který spustil segment, například UIButton po stisknutí nebo UITableViewCell, který spustí segment jeho výběrem. To umožňuje určit, co spustilo segue v příkazu prepareForSegue:sender:, a na základě toho (a samozřejmě identifikátoru segue) provést nějaké akce a nakonfigurovat cílový řadič zobrazení, nebo dokonce určit, že by neměl segue vůbec provádět, vrácením false v příkazu shouldPerformSegueWithIdentifier(_:sender:).
Když není možné spustit segue z prvku uživatelského rozhraní ve Storyboardu, musíte místo toho použít performSegueWithIdentifier(_:sender:) a spustit jej ručně. K tomu může dojít, když žádná přímá interakce uživatele nemá spustit akci nějakého ovládacího prvku, který byl vytvořen v kódu. Možná chcete provést nějakou dodatečnou logiku při stisknutí tlačítka a poté provést segue. Ať už je situace jakákoli, můžete argument odesílatele využít ve svůj prospěch. V příkazu prepareForSegue(_:sender:) nebo shouldPerformSegueWithIdentifier(_:sender:) můžete předat cokoli, co budete potřebovat.
Podívejme se na několik příkladů.
Máme zde dva velmi jednoduché řadiče zobrazení. První má tři tlačítka pro různé barvy. Po klepnutí na některé z tlačítek se název vybrané barvy umístí na štítek a stiskne druhý řadič zobrazení. Stlačený řadič zobrazení nastaví svou barvu pozadí na barvu reprezentovanou klepnutým tlačítkem. K tomu potřebujeme cílovému řadiči zobrazení předat objekt UIColor.
Přestože by se to dalo vyřešit vytvořením 3 různých segmentů z tlačítek přímo do cílového řadiče zobrazení, rozhodli jsme se klepnutí na tlačítko zpracovat sami a segment spustit ručně.
Pro dosažení tohoto cíle můžete vymyslet něco jako následující kód:
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
var tappedColor: UIColor?
@IBAction func tappedRed(sender: AnyObject) {
label.text = „Taped 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
}
}
Vytvořili jsme stavovou proměnnou tappedColor pro sledování barvy, kterou je třeba předat. Nastavíme ji v každé z metod akce před voláním performSegueWithIdentifier(„ShowColor“, odesílatel: sender) a poté ji znovu načteme v prepareForSegue(_:sender:), abychom ji mohli předat cílovému řadiči zobrazení.
Metody akce budou mít jako argument odesílatele nastaveno klepnuté tlačítko UIButtons, a protože je to skutečný prvek, který akci inicioval, dává smysl nastavit jej jako odesílatele při provádění segue. To je tedy to, co děláme ve výše uvedeném kódu. Ale protože ve skutečnosti při přípravě segue odesílatele nepoužíváme, můžeme místo toho rovnou předat barvu. Zde je nová verze ViewControlleru, která přesně toto dělá:
třída 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
}
}
}
}
To nám umožňuje zbavit se naší dodatečné proměnné tappedColor.
Může se však zdát (a možná se tak i děje), že se parametr sender zneužívá, proto jej používejte opatrně a jen tam, kde je to vhodné. Uvědomte si důsledky; pokud nějaký jiný kód nebo nějaký prvek ve Storyboardu spustí stejný segment (tj. se stejným identifikátorem), pak může být odesílatelem právě prvek uživatelského rozhraní namísto očekávaného objektu, což povede k neočekávaným výsledkům a možná i k pádům při násilném obsazení odesílatele na něco, co jím není.
Ukázkový kód v podobě projektu Xcode najdete na https://github.com/lammertw/SegueColorSample.
Podívejte se na naše poradenské služby, nabídky školení a kariéry níže nebo nás kontaktujte na [email protected]
.