Xebia Blog

Jednym z minusów używania segmentów w storyboardach jest to, że często nadal trzeba napisać kod, aby przekazać dane ze źródłowego kontrolera widoku do docelowego kontrolera widoku. Metoda prepareForSegue(_:sender:) jest właściwym miejscem, aby to zrobić. Czasami musisz ręcznie wyzwolić segue przez wywołanie performSegueWithIdentifier(_:sender:), i to właśnie tam zazwyczaj wiesz, jakie dane musisz przekazać. Jak możemy uniknąć dodawania dodatkowych zmiennych stanu w naszym kontrolerze widoku źródłowego tylko po to, aby przekazać dane? Prostą sztuczką jest użycie parametru sender, który posiadają obie metody.

Update:
Proszę pamiętać, że jest to uważane za anty-wzorzec, jak zostało to skomentowane przez niektórych czytelników poniżej, ten post ma na celu zbadanie możliwości segmentów, co nie oznacza, że powinieneś zawsze z nich korzystać. Użyj go tylko wtedy, gdy jest to właściwe lub gdy nie ma innej opcji.

Parametr sender jest zwykle używany przez storyboardy, aby wskazać element UI, który wyzwolił segment, na przykład UIButton po naciśnięciu lub UITableViewCell, który wyzwala segment przez wybranie go. Pozwala to określić, co wywołało segue w prepareForSegue:sender:, i na tej podstawie (i oczywiście identyfikatora segue) podjąć pewne działania i skonfigurować kontroler widoku docelowego, lub nawet określić, że nie powinien on w ogóle wykonywać segue poprzez zwrócenie false w shouldPerformSegueWithIdentifier(_:sender:).

Gdy nie jest możliwe wyzwolenie segue z elementu UI w Storyboard, należy użyć performSegueWithIdentifier(_:sender:) zamiast tego, aby ręcznie go wyzwolić. Może się to zdarzyć, gdy żadna bezpośrednia interakcja użytkownika nie powinna wyzwalać akcji jakiejś kontrolki, która została utworzona w kodzie. Może chcesz wykonać jakąś dodatkową logikę po naciśnięciu przycisku i po tym wykonać segue. Niezależnie od sytuacji, możesz użyć argumentu sender na swoją korzyść. Możesz przekazać cokolwiek, czego możesz potrzebować w prepareForSegue(_:sender:) lub shouldPerformSegueWithIdentifier(_:sender:).

Przyjrzyjrzyjmy się kilku przykładom.

Screen Shot 2015-05-08 at 23.25.37

Tutaj mamy dwa bardzo proste kontrolery widoku. Pierwszy z nich posiada trzy przyciski dla różnych kolorów. Po stuknięciu w którykolwiek z przycisków, nazwa wybranego koloru zostanie umieszczona na etykiecie i będzie ona popychać drugi kontroler widoku. Pchnięty kontroler widoku ustawi swój kolor tła na kolor reprezentowany przez stuknięty przycisk. Aby to zrobić, musimy przekazać obiekt UIColor do docelowego kontrolera widoku.

Mimo że można to było zrobić, tworząc 3 odrębne segmenty z przycisków bezpośrednio do docelowego kontrolera widoku, zdecydowaliśmy się sami obsłużyć stuknięcie przycisku i wywołać segment ręcznie.

Możesz wymyślić coś takiego jak następujący kod, aby to osiągnąć:

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
}

}

Utworzyliśmy zmienną stanową o nazwie tappedColor, aby śledzić kolor, który należy przekazać. Jest ona ustawiana w każdej z metod akcji przed wywołaniem performSegueWithIdentifier(„ShowColor”, sender: sender), a następnie odczytywana ponownie w prepareForSegue(_:sender:), abyśmy mogli przekazać ją do docelowego kontrolera widoku.

Metody akcji będą miały ustawione stuknięte przyciski UIButtons jako argument sender, a ponieważ jest to rzeczywisty element, który zainicjował akcję, sensowne jest ustawienie go jako nadawcy podczas wykonywania segue. Więc to jest to, co robimy w powyższym kodzie. Ponieważ jednak nie używamy nadawcy podczas przygotowywania segue, równie dobrze możemy przekazać kolor bezpośrednio. Oto nowa wersja kontrolera ViewController, która robi dokładnie to samo:

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

}

To pozwala nam pozbyć się naszej dodatkowej zmiennej tappedColor.

Może się wydawać (i być może tak jest), że nadużywamy parametru sender, więc używaj go ostrożnie i tylko tam, gdzie jest to właściwe. Bądź świadomy konsekwencji; jeśli jakiś inny kod lub jakiś element w Storyboard wyzwala ten sam segment (tj. z tym samym identyfikatorem), wtedy nadawca może być po prostu elementem UI zamiast obiektu, którego się spodziewałeś, co doprowadzi do nieoczekiwanych wyników i być może nawet awarii, gdy wymusisz rzutowanie nadawcy na coś, czym nie jest.

Przykładowy kod w postaci projektu Xcode można znaleźć na stronie https://github.com/lammertw/SegueColorSample.

Czy chcesz dowiedzieć się więcej na ten temat?
Spójrz na nasze usługi doradcze, oferty szkoleniowe i kariery poniżej lub skontaktuj się z nami pod adresem [email protected]

.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.