18. Juni 2018

Code und Storyboards verknüpfen mit Outlets und Actions

Mit der Eigenschaft Custom Class im Identity Inspector kann eine Klasse angegeben werden, die für das im Storyboard konfigurierte Objekt zur Laufzeit instanziiert wird. Von dieser Möglichkeit wird vor allem bei View-Controllern Gebrauch gemacht, um eine Klasse einzubinden, die das Verhalten des jeweiligen Screens realisiert:

Identity Inspector: Custom Class

Eigenschaften werden mit @IBOutlet zur Verknüpfung im Interface Builder markiert:

class ExampleViewController : UIViewController {

    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var label: UILabel!

}

Mit @IBAction werden Ereignisbehandlungs-Methoden zur Verknüpfung im Interface Builder markiert:

@IBAction func onTouch() {
    print("Button tapped!")
}

Optional kann dabei das auslösende View- und Event-Objekt als Parameter übergeben werden:

@IBAction func onTouch(sender: UIButton) { /* ... */ }
@IBAction func onTouch(sender: UIButton, forEvent: UIEvent) { /* ... */ }

Verknüpfen von IBOutlets und IBActions

Im Connections Inspector ⌥⌘6 werden die IBOutlet-Eigenschaften und IBAction-Methoden des Controllers angezeigt und diese können mit Views verknüpft werden:

Connections Inspector

Im Code werden die Verknüpfungen mit dem Storyboard angezeigt:

Verknüpfungen zum Code

Für die Verknüpfung von Actions und Outlets ist der Assistant Editor ⌥⌘Enter praktisch. Mit der Auswahl Automatic zeigt der Assistant Editor immer die Klasse zu dem ausgewählten Controller an:

Assistant Editor

Alternativ kann mit Alt-Klick die im Identity Inspector angegebene Klasse im Assistant Editor geöffnet werden:

Assistant Editor über die Klasseneigenschaft öffnen

Mit dem eingeblendeten Assistant Editor können Views direkt mit Outlets und Actions im Code verbunden werden bzw. neue Outlet-Eigenschaften und Action-Methoden direkt erstellt werden, indem eine Verbindung mit der rechten Maustaste bzw. mit gedrückter Ctrl-Taste gezogen wird:

IBOutlet-Eigenschaften and IBAction-Methoden im Assistant Editor erstellen

Tutorial 1: Button-Touch mit einer IBAction-Methode behandeln

  1. Laden Sie den Start-Stand von dem Flashcards-Beispielprojekt: Flashcards.zip.

  2. Deklarieren Sie in CardViewController.swift eine Eigenschaft textLabel als @IBOutlet, um sie mit dem Storyboard verknüpfen zu können. Deklarieren Sie sie als weak (diese Konvention wird später im Kapitel zur Speicherverwaltung behandelt) und verwenden Sie nach der Typangabe ein Ausrufezeichen ! um die Optionalität zu behandeln (dies wird im folgenden Kapitel zu Swift Optionals erklärt):

    class CardViewController: UIViewController {
    
        @IBOutlet weak var textLabel : UILabel!
    
        override func viewDidLoad() {
            // ...
        }
        
        // ...
    
    }
  3. Implementieren Sie die viewDidLoad-Methode so, dass der Vorderseiten-Text standardmäßig gesetzt wird:

    override func viewDidLoad() {
        super.viewDidLoad()
        self.textLabel.text = card.frontText
    }
  4. Deklarieren Sie eine Methode flip als @IBAction zur Verknüpfung im Storyboard und setzen Sie dem Text-View hier den Text der Rückseite:

    @IBAction func flip() {
        self.textLabel.text = card.backText
    }
  5. Starten Sie die App testweise und untersuchen Sie den auftretenden Fehler - die Eigenschaft textLabel wird aktuell noch nicht gesetzt.

  6. Öffnen Sie das Storyboard und blenden Sie den Assistant Editor ⌥⌘Enter ein. Wählen Sie in der Jumpbar den Eintrag Automatic, so dass der Assistant Editor die Klasse zu dem ausgewählten Controller anzeigt:

    Assistant Editor
  7. Ziehen Sie mit der rechten Maustaste bzw. gedrückter Ctrl-Taste eine Verbindung vom Text-Label im Storyboard zu der textLabel-Eigenschaft im Code. Achten Sie dabei darauf, dass die Verbindung als Connect Outlet angezeigt wird:

    Action verbinden im Storyboard

  8. Ziehen Sie analog eine weitere Verbindung vom Flip-Button zu der flip-Methode, achten Sie darauf, dass die Verbindung als Connect Action angezeigt wird.

  9. Starten Sie die App testweise und prüfen Sie die korrekte Funktion des Flip-Buttons.

  10. Erstellen Sie weitere IBOutlet-Eigenschaften btnWrong, btnFlip und btnCorrect indem Sie vom Storyboard eine Verbindung in den Code der CardViewController-Klasse im Assistant Editor ziehen (auf diesem Weg wird die Eigenschaft automatisch angelegt und mit dem Storyboard verknüpft):

    IBOutlets anlegen

  11. Erstellen Sie weitere Action-Methoden wrong und correct, indem Sie im Storyboard Verknüpfungen ziehen. Lassen Sie die erstellten Methoden eine Konsolenausgabe mit print tätigen:

    @IBAction func wrong() {
        print("wrong")
    }
    
    @IBAction func correct() {
        print("correct")
    }
  12. Implementieren Sie viewDidLoad so, dass initial nur der Flip-Button angezeigt wird und auf der Rückseite nur die Buttons Wrong und Correct sichtbar sind.

    override func viewDidLoad() {
        super.viewDidLoad()
        self.textLabel.text = card.frontText
        self.btnWrong.isHidden = true
    self.btnFlip.isHidden = false
    self.btnCorrect.isHidden = true
    }
    
    @IBAction func flip() {
        self.textLabel.text = card.backText
        self.btnWrong.isHidden = false
    self.btnFlip.isHidden = true
    self.btnCorrect.isHidden = false
    }
  13. Starten Sie die App und testen Sie die Implementierung.

  14. Übernehmen Sie die Änderungen mit Source Control » Commit als „7.1. CardViewController-Flip implementiert“.

Tutorial 2: Methoden umbenennen und Action-Verbindungen lösen

  1. Benennen Sie die Action-Methode manuell im Code zu flipRenamed um. Beachten Sie, dass im Lineal des Code-Editors angezeigt wird, dass die Verbindung nicht mehr besteht:

  2. Starten Sie die App und tippen Sie auf den Button. Sie sollten mit einem SIGABRT-Crash der App, die vom Debugger gefangen wird, konfrontiert werden. Machen Sie sich mit der Fehleranzeige in der Console der Debug Area vertraut und scrollen Sie zur eigentlichen Fehlermeldung „unrecognized selector sent to instance ...“:

    Fehlermeldung im Xcode-Debugger: Unrecognized selector sent to instance

    Sie können aus der Fehlermeldung erkennen, dass versucht wurde auf einem CardViewController-Objekt weiterhin die Methode flip aufzurufen, diese nun jedoch nicht mehr existiert (unrecognized selector ist ein Begriff aus Objective-C: Die Signatur einer Methode wird als Selector bezeichnet).

    [Flashcards.CardViewController flip]: unrecognized selector sent to instance ...
  3. Klicken Sie im Storyboard mit der rechten Maustaste / mit gedrückter Ctrl-Taste auf den Button und lösen Sie im erscheinenden Connections Inspector die bestehende Verbindung:

    Lösen einer Outlet-Verbindung im Connections Inspector
  4. Ziehen Sie eine neue Verbindung zu der soeben umbenannten Methode und testen Sie, dass die App nun wieder korrekt funktioniert.

  5. Dieses Tutorial diente lediglich zum besseren Verständnis der Verknüpfung zwischen Code und Storyboard. Verwerfen Sie Ihre Änderungen mit Source Control » Discard All Changes..., um das Projekt auf den zuvor committeten Stand zurückzusetzen.