Шаблон делегирования в Какао используется, чтобы информировать (сообщать о ходе выполнения и т. Д.) Или запрашивать (запрашивать учетные данные и т. Д.) Другой объект, не зная об этом много.
Как правило, вы используете протокол дляОпределите, какие методы вы будете вызывать для делегата, и тогда делегат должен соответствовать этому протоколу.Вы также можете добавить методы, которые делегату не нужно реализовывать (необязательно).Когда вы это сделаете, вам придется вызывать -respondsToSelector :, потому что вы не знаете, хочет ли делегат вызывать конкретный метод или нет.
Пример:
У вас есть классчто-то производит, назовем это Machine
и рабочий класса Worker
.Машина должна быть настроена для задачи:
Machine *machine = [[Machine alloc] init];
[machine prepareWithParameters:myParameters];
Теперь, когда у нас есть машина, мы хотим произвести огромное количество Stuff
:
[machine produceStuff];
Хорошо, мысделано.Но как мы узнаем, когда была произведена единица Stuff
?Мы могли бы иметь нашего работника, постоянно стоящего рядом с нашей машиной, и ждать:
while (![machine isFinished]) {
if ([machine didProduceStuff]) {
Stuff *stuff = [machine producedStuff];
[self doSomethingWithStuff:stuff];
}
else {
// Get a very large coffee...
}
}
Разве не было бы здорово, если бы машина действительно сообщала нам автоматически, когда она закончила с производством единицы Stuff
?
@protocol MachineDelegate <NSObject>
@optional
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff;
@end
Давайте добавим worker
в качестве делегата machine
:
Worker *worker;
Machine *machine = [[Machine alloc] init];
[machine prepareWithParameters:myParameters];
[machine setDelegate:worker]; // worker does conform to <MachineDelegate>
[machine produceStuff];
Когда Machine
завершит создание чего-либо, он вызовет:
if ([[self delegate] respondsToSelector:@selector(machine:didProduceStuff:)])
[[self delegate] machine:self didProduceStuff:stuff];
Затем worker
получит этот метод и может что-то сделать:
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff {
[self doSomethingWithStuff:stuff];
if ([machine isFinished])
[self shutDownMachine:machine];
}
Разве это не намного эффективнее и проще для работника?Теперь он может сделать что-то более продуктивное, чем стоять рядом с машиной, пока машина все еще работает.Теперь вы можете добавить еще больше методов к MachineDelegate
:
@protocol MachineDelegate <NSObject>
@required
- (void) machineNeedsMaintenance:(Machine *)machine;
- (void) machine:(Machine *)machine fatalErrorOccured:(Error *)error;
- (BOOL) machine:(Machine *)machine shouldContinueAfterProductionError:(Error *)error;
@optional
- (void) machineDidEnterEcoMode:(Machine *)machine;
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff;
@end
Делегаты также можно использовать для изменения поведения объекта без его подкласса:
@protocol MachineDelegate <NSObject>
@required
- (Color *) colorForStuffBeingProducedInMachine:(Machine *)machine;
- (BOOL) machineShouldGiftWrapStuffWhenDone:(Machine *)machine;
@end
Я надеюсь, что смогупоможет вам понять преимущества абстрагирования кода с помощью делегатов.