Delegasi Swift dan callback dalam bahasa yang sederhana. Apa delegasi ini dan bagaimana cara kerja panggilan balik?

Di Swift, ketika mempelajari UI (Antarmuka Pengguna), cepat atau lambat, semua orang harus menggunakan delegasi. Semua panduan menulis tentang mereka, dan Anda tampaknya melakukan apa yang tertulis di sana, dan tampaknya berhasil, tetapi mengapa dan bagaimana cara kerjanya, tidak semua orang di kepala mereka cocok sampai akhir. Secara pribadi, saya bahkan merasa untuk sementara waktu bahwa delegasi adalah semacam kata ajaib, dan itu secara langsung dibangun ke dalam bahasa pemrograman (begitulah pikiran saya membingungkan dari panduan ini). Mari kita coba jelaskan secara sederhana apa itu. Dan begitu Anda memahami delegasi, akan lebih mudah untuk memahami apa itu callback dan cara kerjanya.



Pelayan dan koki



Jadi, sebelum beralih ke kodenya, mari kita bayangkan seorang pelayan dan beberapa koki. Pelayan menerima pesanan dari klien di meja, tetapi dia sendiri tidak tahu cara memasak, dan dia perlu bertanya kepada juru masak tentang hal itu. Dia bisa pergi ke dapur dan memberi tahu juru masak, "Masak ayam." Juru masak memiliki peralatan yang sesuai (wajan, minyak, api ...) dan keterampilan memasak. Juru masak menyiapkan dan memberikan hidangan kepada pelayan. Pelayan mengambil apa yang dibuat oleh koki dan membawanya ke klien.



Sekarang mari kita bayangkan situasi di mana seorang pelayan tidak bisa berlari ke dapur dan memberi tahu juru masak secara langsung hidangan mana yang dipesan darinya. Mereka tidak mengizinkannya ke dapur (misalnya, aturan seperti itu) atau dapur ada di lantai lain (Anda bosan berlari). Dan satu-satunya cara untuk berkomunikasi adalah melalui jendela lift mini. Pelayan menaruh catatan di sana, menekan tombol, lift menuju dapur. Hadir kembali dengan hidangan yang sudah disiapkan. Apakah kamu ingat? Sekarang mari kita perbaiki situasi di kepala kita, coba buat ulang melalui kode dan pahami kaitannya dengan topik kita.



Mari transfer ke kode



Kami menciptakan kelas pelayan dan memasak. Untuk kesederhanaan, mari lakukan ini di taman bermain:



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
    }

}


Sekarang kami membuat salinannya (kami mempekerjakan mereka), dan meminta pelayan untuk menerima pesanan (ayam):



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

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


Bagaimana pelayan bisa memberi tahu juru masak apa yang harus dimasak sekarang?



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