Swift - Delegate: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
Zeile 15: Zeile 15:
 
Aber wie kann man dieses Pattern nun realisieren, und wie kann man ein Objekt zum Delegat machen?
 
Aber wie kann man dieses Pattern nun realisieren, und wie kann man ein Objekt zum Delegat machen?
  
Um dies zu realisieren werden Protocols verwendet. Im Beispiel mit den Textfields sieht das vereinfacht etwa so aus:
+
Um dies zu realisieren werden Protocols verwendet.  
 +
 
 +
Hier ein Beispiel
  
 
<syntaxhighlight lang="swift">
 
<syntaxhighlight lang="swift">
// this protocol is used by
+
 
protocol UITextFieldDelegate{
+
/**
  func textFieldDidBeginEditing()
+
who wants to do ADL must know hot to perform CPR (Wiederbelebung)
 +
*/
 +
protocol AdvancedLifeSupport{
 +
    func performCPR()
 +
}
 +
 
 +
/**
 +
If a emergency call comes in the EmergencyCallHandler is responsible to address the situation an inform a delegate
 +
*/
 +
class EmergencyCallHandler {
 +
   
 +
    var delegate: AdvancedLifeSupport? // the med pager ;-)
 +
   
 +
    func assessSituation() {
 +
        print("Can you tell me what happended?")
 +
    }
 +
    func triggerMedicalEmergency() {
 +
        delegate?.performCPR()
 +
    }
 +
}
 +
 
 +
/**
 +
When the paramedic goes on shift and picks up the emergency pager (meaning he sets the delegate to himself)
 +
*/
 +
struct Paramedic: AdvancedLifeSupport{
 +
   
 +
    init(handler: EmergencyCallHandler) {
 +
        handler.delegate = self
 +
    }
 +
   
 +
    func performCPR() {
 +
        print("The paramedic does chest compressions 30 per second.")
 +
    }
 +
}
 +
 
 +
class Doctor: AdvancedLifeSupport{
 +
   
 +
    init(handler: EmergencyCallHandler){
 +
        handler.delegate = self
 +
    }
 +
    func performCPR() {
 +
        print("The doctor does chest compressions 30 per second.")
 +
    }
 +
    func useStethoscope(){
 +
        print("Doctor listening for heart sounds.")
 +
    }
 
}
 
}
  
// UITextField is delegating via delegate variable and defines the protocol functions as function of the delegate var...
+
class Surgeon: Doctor{
class UITextField, UITextFieldDelegate{
+
    override func performCPR() {
  var delegate: UITextFieldDelegate
+
        super.performCPR()
  delegate.textFieldDidBeginEditing()
+
        print("Singing Staying alive by the BeeGees")
 +
    }
 +
    func useElectricDrill(){
 +
        print("Whirr...")
 +
    }
 
}
 
}
  
  // ...
+
 
  // Now in a class that should be the delegat you do:
+
let emma = EmergencyCallHandler()
    
+
let pete = Paramedic(handler: emma)
 +
let angela = Surgeon(handler: emma)
 +
/**
 +
note that pete will not get informed because the dalegate property (the pager) has changed to angela
 +
if you uncomment angela pete will do CPR
 +
*/
 +
 
 +
emma.assessSituation()
 +
emma.triggerMedicalEmergency()
 +
</syntaxhighlight>
 +
 
 +
Im Beispiel mit den Textfields gibt es also ein Protocol, welches vorgibt welche Funktionalität ein Delegat erfüllen muss.
 +
Sobald unsere Klasse das Delegat erhält müssen wir die zum Protokoll zugehörigen Funktionen implementieren.
 +
 
 +
<syntaxhighlight lang="swift">
 +
 
 +
class myClass{
 +
   /...
 
   let textField = UITextField
 
   let textField = UITextField
 
   textField.delegate = self // now textFieldDidBeginEditing() is delegated to self
 
   textField.delegate = self // now textFieldDidBeginEditing() is delegated to self
 +
  //...
 
</syntaxhighlight>
 
</syntaxhighlight>
 
Wenn also einem Delegat ein UITextFieldDelegate Typ zugewiesen ist kann das delegierende Objekt sicher sein, dass auch die Funktion textFieldDidBeginEditing unterstützt wird.
 

Version vom 7. Januar 2023, 23:02 Uhr

Links

Swift (Programmiersprache)
Swift - Protocols

Das Delegate Design Pattern

Das Delegate Design Pattern ist eine Möglichkeit, wie man bestimmte Aufgaben oder Verhaltensweisen von einem Objekt an ein anderes Objekt delegieren kann. Stell dir vor, du bist der Lehrer einer Schulklasse und du möchtest, dass ein Schüler als Klassenvertreter fungiert und bestimmte Aufgaben für die Klasse übernimmt. Der Schüler wäre in diesem Fall der Delegat und du wärst der Delegierende. Du gibst bestimmte Aufgaben an den Schüler ab, anstatt sie selbst zu erledigen. Auf diese Weise kannst du die Verantwortung für bestimmte Aufgaben teilen und dich auf andere wichtige Dinge konzentrieren.

Das Delegate Design Pattern wird auch in der Softwareentwicklung verwendet, um die Kopplung zwischen verschiedenen Objekten zu verringern und den Code wieder verwenden zu können. Stell dir vor, du hast ein Programm, das einen Timer hat. Du möchtest, dass das Programm etwas tut, wenn der Timer abgelaufen ist. Statt den Code für das, was passieren soll, direkt in den Timer zu schreiben, könntest du das Delegate Design Pattern verwenden. Du könntest ein anderes Objekt als Delegat festlegen und es verantwortlich machen, was passieren soll, wenn der Timer abgelaufen ist. Auf diese Weise wäre der Timer unabhängig von dem, was passiert, wenn er abgelaufen ist, und der Code für das, was passieren soll, könnte an anderer Stelle im Programm geschrieben werden.

In Swift werden Delegates an vielen Stellen verwendet. Ein Beispiel sind Texteingabefelder (TextViews). Bevor ein Programm geschrieben ist weiß man nicht wie es auf Texteingaben des Benutzer reagieren soll. Deshalb können TextViews diese Aufgabe delegieren. Der Programmierer kann dann später selbst entscheiden wie sein Programm auf aktuelle Texteingaben reagiert.

Das Textfeld - der Delegierende gibt dafür dem Delegat bescheid wenn etwas passiert (z.b. der User die Eingabe beendet) und der Delegat kann dann reagieren (z.B. die Tastatur schließen)

Delegate und Protocol

Aber wie kann man dieses Pattern nun realisieren, und wie kann man ein Objekt zum Delegat machen?

Um dies zu realisieren werden Protocols verwendet.

Hier ein Beispiel

/**
 who wants to do ADL must know hot to perform CPR (Wiederbelebung)
 */
protocol AdvancedLifeSupport{
    func performCPR()
}

/**
 If a emergency call comes in the EmergencyCallHandler is responsible to address the situation an inform a delegate
 */
class EmergencyCallHandler {
    
    var delegate: AdvancedLifeSupport? // the med pager ;-)
    
    func assessSituation() {
        print("Can you tell me what happended?")
    }
    func triggerMedicalEmergency() {
        delegate?.performCPR()
    }
}

/**
 When the paramedic goes on shift and picks up the emergency pager (meaning he sets the delegate to himself)
 */
struct Paramedic: AdvancedLifeSupport{
    
    init(handler: EmergencyCallHandler) {
        handler.delegate = self
    }
    
    func performCPR() {
        print("The paramedic does chest compressions 30 per second.")
    }
}

class Doctor: AdvancedLifeSupport{
    
    init(handler: EmergencyCallHandler){
        handler.delegate = self
    }
    func performCPR() {
        print("The doctor does chest compressions 30 per second.")
    }
    func useStethoscope(){
        print("Doctor listening for heart sounds.")
    }
}

class Surgeon: Doctor{
    override func performCPR() {
        super.performCPR()
        print("Singing Staying alive by the BeeGees")
    }
    func useElectricDrill(){
        print("Whirr...")
    }
}


let emma = EmergencyCallHandler()
let pete = Paramedic(handler: emma)
let angela = Surgeon(handler: emma)
/**
 note that pete will not get informed because the dalegate property (the pager) has changed to angela
 if you uncomment angela pete will do CPR
 */

emma.assessSituation()
emma.triggerMedicalEmergency()

Im Beispiel mit den Textfields gibt es also ein Protocol, welches vorgibt welche Funktionalität ein Delegat erfüllen muss. Sobald unsere Klasse das Delegat erhält müssen wir die zum Protokoll zugehörigen Funktionen implementieren.

class myClass{
  /...
  let textField = UITextField
  textField.delegate = self // now textFieldDidBeginEditing() is delegated to self
  //...