在Swift中,迟早学习UI(用户界面)时,每个人都需要使用委托。所有指南都写有关于它们的内容,您似乎正在按照此处编写的内容进行操作,并且似乎可以正常运行,但是它为什么起作用以及如何起作用,并不是每个人都能接受。就个人而言,我什至有一段时间感觉到委托是某种神奇的词,它直接内置于编程语言中(这使我从这些指南中产生的想法感到困惑)。让我们尝试简单地解释一下它是什么。而且,一旦您了解了委托,就会更容易理解回调是什么以及它如何工作。
服务员和厨师
因此,在继续编写代码之前,让我们想象一下某个服务生和一些厨师。服务员从餐桌上的客户那里接到订单,但他本人不知道如何烹饪,因此需要向厨师询问。他可以去厨房告诉厨师:“煮鸡。”厨师具有适当的工具(煎锅,油,火...)和烹饪技巧。厨师准备并将菜交给服务员。服务员把厨师做的东西带给客户。
现在,让我们想象一下这样一种情况:服务员无法跑到厨房去,直接告诉厨师是从他那里订购的菜。他们不允许他进入厨房(例如,此类规则),或者厨房不在另一层(您已经厌倦了跑步)。交流的唯一方法是通过微型电梯窗口。服务员在那儿放一张纸条,按下按钮,电梯去了厨房。回来准备的菜。你还记得吗?现在让我们解决这个问题,尝试通过代码重新创建它,并了解它与我们的主题之间的关系。
让我们转移到代码
我们创建服务员和厨师课程。为简单起见,让我们在操场上进行以下操作:
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
}
}
现在,我们创建他们的副本(我们雇用他们工作),并要求服务员接收订单(鸡肉):
// ( ):
let waiter = Waiter()
let cook = Cook()
// . , :
waiter.takeOrder("Chiken")
服务员如何告诉厨师现在要煮什么?
, , 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 ( ).
:
- :
// :
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!
*/
:
- (), , , , - .
- «» .
- (, ) , ( )
- , 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)
}
. , . !