In den letzten beiden Tutorials hatten wir uns angeschaut, wie die "show" und "present" segues verwendet werden und wie Daten an den Ziel-ViewController übergeben werden. Lasst uns nun schauen, wie wir mithilfe von “delegates” Daten von dem Ziel-ViewController zu den ursprünglichen zurückgeben können.
Das Delegate Muster
Das “delegate” Muster ist eines der häufigsten Muster in iOS. Das Konzept ist recht einfach. Es ermöglicht die Kommunikation zwischen zwei Objekten, während eines die Verantwortung an ein anderes delegiert. Es wird häufig mithilfe von Protokollen implementiert. Ein Protokoll besteht im Wesentlichen aus einer Reihe von Funktionen oder Eigenschaften und anderen Anforderungen.
Das Protokoll enthält nur eine Beschreibung der Anforderungen (functions signatures, properties types, properties names, usw.). Diese sind jedoch noch nicht implementiert. Sie werden erst implementiert, wenn das Protokoll unter anderem von einer Klasse übernommen wird.
Delegate hinzufügen
Betrachten wir mal den folgenden Fall: Wir navigieren von ViewController zu einem anderen ViewController2. Wenn wir zurück navigieren, möchten wir in ViewController einen Text abrufen und anzeigen, den der Benutzer in ViewController2 eingegeben hat.
Dafür erstellen wir ein Protokoll namens ViewController2Delegate. Es enthält eine Methode, die darüber benachrichtigt, dass ViewController2 geschlossen ist und den Text an ViewController weitergeleitet hat. Gehe wie folgt vor, um ein “delegate” hinzuzufügen:
Öffne die Datei ViewController2.swift.
Füge vor der "class" Deklaration folgenden Code hinzu.
protocol ViewController2Delegate: AnyObject {
func viewDidClose(withText text: String?)
}
class ViewController2: UIViewController {
....
Füge in der Klasse ViewController2 eine neue Variable vom Typ ViewController2Delegate hinzu.
class ViewController2: UIViewController {
weak var delegate: ViewController2Delegate?
....
Füge im Storyboard ein neues TextField zu ViewController2 hinzu, platziere es mithilfe von Constraints und verknüpfe es mit der Variablen des TextField namens textField (weitere infos dazu in diesem Tutorial oder im Video unten).
Gehe zurück zu ViewController2.swift, bearbeite die Funktion “close screen”, um die “delegate” Methode aufzurufen und den delegate darüber zu informieren, dass die Ansicht geschlossen wird und übergebe gleichzeitig den über textField eingegebenen Textwert.
@IBAction func closeScreen(sender: UIButton) {
delegate?.viewDidClose(withText: textField?.text)
dismiss(animated: true, completion: nil)
}
Bisher haben wir also einen Variable “delegate” erstellt, der die Funktion "viewDidClose" aufruft, wenn die Funktion closeScreen aufgerufen wird, wobei der Text als Parameter verwendet wird.
Zu diesem Zeitpunkt legt noch niemand den Wert der Variable “delegate” fest. Der Wert ist immer noch Null. Das bedeutet, dass nichts passiert, bis diese Variable von einem anderen Objekt festgelegt wird, um mit dem Empfang von Nachrichten zu beginnen.
Implementieren des Protokolls und Festlegen des “delegate”
Bei dem Protokoll handelt es sich nur um die Deklaration von Anforderungen, die noch nicht implementiert sind. Um sie zu implementieren, muss eine Klasse (oder eine struct usw.) das Protokoll übernehmen und eine Implementierung gemäß ihren Anforderungen definieren. In unserem Fall möchten wir, dass unserer ViewController der “delegate” für ViewController2 wird. Dafür muss der ViewController den ViewController2Delegate implementieren und die ViewController2 delegate variable auf sich selbst setzen.
Öffne ViewController.swift.
Bearbeite die Class Deklaration, um das ViewController2Delegate Protokoll zu implementieren.
class ViewController: UIViewController, ViewController2Delegate {
....
Es wird ein Fehler angezeigt, der darauf hinweist, dass ViewController nicht dem Protokoll entspricht. Dies liegt daran, dass nicht alle Anforderungen des Protokolls implementiert werden. In unserem Fall ist das die Funktion "viewDidClose". Ein Objekt, dass ein Protokoll übernimmt, muss eine Implementierung gemäß seinen Anforderungen bereitstellen. Wir fügen dafür also der Klasse den folgenden Code hinzu:
func viewDidClose(withText text: String?) {
messageLabel.text = text
}
Und schließlich müssen wir zur Vorbereitung auf den Übergang die ViewController2 delegate Variable gleich der ViewController Instanz selbst setzen und die bereits vorhandene prepare(for segue:) bearbeiten. Dafür fügen wir folgende Codezeile hinzu, mit der diese Variable festgelegt wird:
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
if segue.identifier == "NavigationToScreen2" {
let viewController2 = segue.destination as? ViewController2
// ADD THIS LINE OF CODE TO THE EXISTING IMPLEMENTATION
viewController2?.delegate = self
....
Führe nun die App aus, navigiere zum ViewController2 und gebe einen beliebigen Text in das gerade hinzugefügte Textfeld ein. Tippe dann auf den "close Button". Der eingegebene Text sollte jetzt auf dem Label in ViewController angezeigt werden.
Die Projektdateien kannst Du wieder hier herunterladen.
Verpasse kein Tutorial mehr! Like dafür einfach unsere Facebook Seite oder abonniere unseren YouTube Channel ✅
Also: Bleib dran!
Viel Spaß beim Coden.
Euer Code Pirate Team
Du liest: Navigation zwischen UIViewController - Teil 3
コメント