Schnelle Delegierte und Rückrufe im Klartext. Was ist dieser Delegat und wie funktioniert der Rückruf?

Wenn in Swift früher oder später die Benutzeroberfläche (User Interface) erlernt wird, muss jeder einen Delegaten verwenden. Alle Führer schreiben über sie, und Sie scheinen zu tun, wie es dort geschrieben steht, und es scheint zu funktionieren, aber warum und wie es funktioniert, passt nicht jeder in ihrem Kopf zum Ende. Persönlich hatte ich sogar für eine Weile das Gefühl, dass Delegierter eine Art Zauberwort ist und dass es direkt in die Programmiersprache eingebaut ist (so verwirrend waren meine Gedanken aus diesen Handbüchern). Lassen Sie uns versuchen, in einfachen Worten zu erklären, was es ist. Sobald Sie den Delegaten verstanden haben, ist es viel einfacher zu verstehen, was ein Rückruf ist und wie er funktioniert.



Kellner und Koch



Bevor wir zum Code übergehen, stellen wir uns einen bestimmten Kellner und einen Koch vor. Der Kellner erhielt eine Bestellung vom Kunden am Tisch, aber er selbst weiß nicht, wie man kocht, und er muss den Koch danach fragen. Er kann in die Küche gehen und dem Koch sagen: "Koch das Huhn." Der Koch verfügt über die entsprechenden Werkzeuge (Pfanne, Öl, Feuer ...) und Kochkünste. Der Koch bereitet das Gericht zu und gibt es dem Kellner. Der Kellner nimmt das, was der Küchenchef gemacht hat und bringt es zum Kunden.



Stellen wir uns nun eine Situation vor, in der ein Kellner nicht in die Küche rennen kann und dem Koch direkt mitteilt, welches Gericht bei ihm bestellt wurde. Sie lassen ihn nicht in die Küche (zum Beispiel solche Regeln) oder die Küche befindet sich auf einer anderen Etage (Sie werden es leid zu rennen). Die einzige Möglichkeit zur Kommunikation ist das Mini-Aufzugsfenster. Der Kellner legt dort eine Notiz ab, drückt den Knopf, der Aufzug fährt in die Küche. Kommt mit einem vorbereiteten Gericht zurück. Erinnerst du dich? Lassen Sie uns nun die Situation in unserem Kopf beheben, versuchen, sie durch den Code neu zu erstellen und zu verstehen, wie dies mit unserem Thema zusammenhängt.



Lassen Sie uns zum Code übertragen



Wir erstellen die Kellner- und Kochkurse. Lassen Sie uns dies der Einfachheit halber auf dem Spielplatz tun:



import UIKit

//   
class Waiter {

    ///  "" -     .      ,  "private".
    private var order: String?

    ///  " ".
    func takeOrder(_ food: String) {
        print("What would you like?")
        print("Yes, of course!")
        order = food
        sendOrderToCook()
    }

    ///  "  ".     .  ?
    private func sendOrderToCook() {
        // ???    ?
    }

    ///  "  ".   .
    private func serveFood() {
        print("Your \(order!). Enjoy your meal!")
    }

}

//   
class Cook {

    ///  "".    .
    private let pan: Int = 1

    ///  "".    .
    private let stove: Int = 1

    ///  "".   .
    private func cookFood(_ food: String) -> Bool {
        print("Let's take a pan")
        print("Let's put \(food) on the pan")
        print("Let's put the pan on the stove")
        print("Wait a few minutes")
        print("\(food) is ready!")
        return true
    }

}


Jetzt erstellen wir Kopien davon (wir stellen sie für die Arbeit ein) und bitten den Kellner, die Bestellung zu erhalten (Huhn):



//       ( ):
let waiter = Waiter()
let cook = Cook()

//     . ,   :
waiter.takeOrder("Chiken")


Wie kann der Kellner dem Koch sagen, was er jetzt kochen soll?



, , private. private, :



cook.cookFood(waiter.order!)
// 'cookFood' is inaccessible due to 'private' protection level
// 'order' is inaccessible due to 'private' protection level


«» , private . "" , ? : " , , ?"



"". . . "" " ":



protocol InterchangeViaElevatorProtocol {
    func cookOrder(order: String) -> Bool
}


, "", , . . , . : , .





, . ().



. , , " ". Xcode . Bool .



cookFood, .



extension Cook: InterchangeViaElevatorProtocol {
    func cookOrder(order: String) -> Bool {
        cookFood(order)
    }
}


" ". , , .



extension Waiter {
    var receiverOfOrderViaElevator: InterchangeViaElevatorProtocol? { return cook }
}


, . return cook.



-: , . .



, . , .



:



import UIKit

protocol InterchangeViaElevatorProtocol {
    func cookOrder(order: String) -> Bool
}

class Waiter {

    //     "   ".  ,        ,   .
    var receiverOfOrderViaElevator: InterchangeViaElevatorProtocol?

    var order: String?

    func takeOrder(_ food: String) {
        print("What would you like?")
        print("Yes, of course!")
        order = food
        sendOrderToCook()
    }

    private func sendOrderToCook() {
        // ???    ?
    }

    private func serveFood() {
        print("Your \(order!). Enjoy your meal!")
    }

}

//   
class Cook: InterchangeViaElevatorProtocol {

    private let pan: Int = 1
    private let stove: Int = 1

    private func cookFood(_ food: String) -> Bool {
        print("Let's take a pan")
        print("Let's put \(food) on the pan")
        print("Let's put the pan on the stove")
        print("Wait a few minutes")
        print("\(food) is ready!")
        return true
    }

    //  ,  ():
    func cookOrder(order: String) -> Bool {
        cookFood(order)
    }

}


private order ( ).



:



  1. :


//      :
let waiter = Waiter()
let cook = Cook()

//   :
waiter.takeOrder("Chiken")


, " " – .



//   ,   "   " -   :
waiter.receiverOfOrderViaElevator = cook


, , , .



" " :



//     "   "   :
waiter.receiverOfOrderViaElevator?.cookOrder(order: waiter.order!)


, !



/*
 What would you like?
 Yes, of course!
 Let's take a pan
 Let's put Chiken on the pan
 Let's put the pan on the stove
 Wait a few minutes
 Chiken is ready!
 */


« », .



«» , « », , .



    private func sendOrderToCook() {
        //   cookOrder   "   ":
        receiverOfOrderViaElevator?.cookOrder(order: order!)
    }


! receiverOfOrderViaElevator, . . delegate, . , , .



? «, – . – UI?»



delegate UI?



UI , «» «». , table view collection view. table view collection view : . . () «» («Delegate»).



, Delegable «». , , !



, – . . Waiter. () hireWaiter. (, -):



//   -
class Chief: InterchangeViaElevatorProtocol {

    private let pan: Int = 1
    private let stove: Int = 1

    private func cookFood(_ food: String) -> Bool {
        print("Let's take a pan")
        print("Let's put \(food) on the pan")
        print("Let's put the pan on the stove")
        print("Wait a few minutes")
        print("\(food) is ready!")
        return true
    }

    //  ,  ():
    func cookOrder(order: String) -> Bool {
        cookFood(order)
    }

    // -      :
    func hireWaiter() -> Waiter {
        return Waiter()
    }

}


- ( - hireWaiter):



//   - (-  ):
let chief = Chief()

// -  :
let waiter = chief.hireWaiter()

//   :
waiter.takeOrder("Chiken")


. , " " – -. .



//  ,   "   " -   -:
waiter.receiverOfOrderViaElevator = chief
//     "   "   :
waiter.receiverOfOrderViaElevator?.cookOrder(order: waiter.order!)


, .



. , -, , « » -.



class SmartChief: Chief {

    override func hireWaiter() -> Waiter {
        let waiter = Waiter()
        waiter.receiverOfOrderViaElevator = self //         
        return waiter
    }

}


SmartChief Chief .



, - (), . !



let smartChief = SmartChief()
let smartWaiter = smartChief.hireWaiter()
smartWaiter.takeOrder("Fish")
/*
 What would you like?
 Yes, of course we have Fish!
 Let's take a pan
 Let's put Fish on the pan
 Let's put the pan on the stove
 Wait a few minutes
 Fish is ready!
 */


:



  1. (), , , , - .
  2. «» .
  3. (, ) , ( )
  4. , self «» .


, «» , , .



. , ! .



(, callback). ? ,



, , «» . , . ? ?



(callback) – , . . .


-,



, - ( , ). , , : «- ! , !» , , . .



.



. . , String Bool. cookFood ! - - .



///   
class TalentedWaiter {

    var order: String?

    //      .  ,        String      Bool.
    var doEverything: ((String) -> Bool)?

    func takeOrder(_ food: String) {
        print("What would you like?")
        print("Yes, of course we have \(food)!")
        order = food
        //    -    :
        doOwnself()
    }

    private func doOwnself() -> Bool {
        //   ,    :
        if let doEverything = doEverything {
            let doOwnself = doEverything(order!)
            return doOwnself
        } else {
            return false
        }
    }

}


-. , , . , . , :



//    -
class LazyChief {

    private let pan: Int = 1
    private let stove: Int = 1

    private func cookFood(_ food: String) -> Bool {
        print("I have \(pan) pan")
        print("Let's put \(food) on the pan!")
        print("I have \(stove) stove. Let's put the pan on the stove!")
        print("Wait a few minutes...")
        print("\(food) is ready!")
        return true
    }

    //    :
    func hireWaiter() -> TalentedWaiter {
        let talentedWaiter = TalentedWaiter()

        //     .       ,       cookFood:
        talentedWaiter.doEverything = { order in
            self.cookFood(order)
        }
        return talentedWaiter
    }

}


-, , , :



let lazyChief = LazyChief()
let talentedWaiter = lazyChief.hireWaiter()
talentedWaiter.takeOrder("Meat")
/*
 What would you like?
 Yes, of course we have Meat!
 I have 1 pan
 Let's put Meat on the pan!
 I have 1 stove. Let's put the pan on the stove!
 Wait a few minutes...
 Meat is ready!
 */


, , «» .



, , . , , ().

– . , self , - , .



[weak self] in . , !



talentedWaiter.doEverything = { [weak self] order in
            self!.cookFood(order)
        }


. , . !



GitHub




All Articles