Делегаты в IOS - Требуется некоторое разъяснение

Я только начинаю разработку IOS, но имею несколько лет разработчика ASP.net через С#. Честно говоря, мне никогда не приходилось действительно понимать делегатов/событий и т.д., Я знаю, что я использую их при программировании web.forms, но многие функции позаботятся об этой структуре, за кулисами.

Итак, теперь, когда я развиваюсь в IOS, я вынужден попытаться понять, как они функционируют (я предполагаю, что теория делегатов/событий одинакова на разных языках, может быть, я ошибаюсь). Во всяком случае, следующая строка кода в IOS:

 if ([self.delegate respondsToSelector:@selector(startImporting:)])
 {
            [self.delegate startImporting:self];
 }

Я прав, думая, что в псевдокоде это означает что-то по строкам:

Если метод/класс, вызывающий этот метод, имеет в нем метод, называемый "startImporting", тогда вызовите метод "startImporting" в вызывающем классе.

Надеюсь, что это ясно. Если это так, то это будет по существу тем же самым, что и статический метод в С#, который вы могли бы вызвать с помощью чего-то вроде:

myImportClass.startImporting();

Предположительно нет, или как это будет сделано. Итак, я пропущу всю точку зрения делегатов, их преимущества и т.д.? Я читал, что они делали снова и снова, и в то время как это имеет смысл, он никогда не нажимает, я никогда (в веб-формах так или иначе) действительно видел выгоду от их использования.

Это становится все более важным, поскольку я перехожу к использованию лямбда-выражений в .net, и они тесно связаны с делегатами на С#, поэтому, когда я могу только начать их использовать, я бы предпочел знать, почему и что польза от делегатов на самом деле есть.

Ответ 1

Шаблон делегирования в Cocoa используется для информирования (отчета о прогрессе и т.д.) или запроса (запрашивать учетные данные и т.д.) другого объекта, не зная об этом.

Как правило, вы используете протокол для определения того, какие методы вы вызываете у делегата, и делегат тогда должен соответствовать этому протоколу. Вы также можете добавить методы, которые делегат не должен выполнять (необязательно). Когда вы это сделаете, вам придется вызвать -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

Надеюсь, я мог бы помочь вам понять, как абстрагировать ваш код с помощью делегатов.

Ответ 2

Понимание модели MVC и использование протоколов и уведомлений имеет решающее значение для понимания использования и назначения делегатов. Подумайте о них как о типах респондентов для разных событий, связанных с конкретным действием.

Hera - это полезные ссылки в stackOverflow:

Надеюсь, что это поможет

Ответ 3

делегаты полезны при получении обратных вызовов из другого класса

так зачем использовать делегат: то есть мы вызываем метод в классе... что нормальный... если мы хотим, чтобы экземплярный класс позвонил нам... что там, где делегаты пригодится...

простой пример: u загружать песни с сайта, используя метод в одном классе как только класс завершит загрузку, вы хотите, чтобы класс дал вам знать...

 //protocol declaration
  @protocol DownloadProtocol <NSObject>
  -(void)OnFinish;
  @end

//SOng download class
@interface songs
@property(Strong,nonatomic) id<DownloadProtcol> delegate;
-(void)Download;
@end
@implementation songs
-(void)Download
{

///the code to download goes here

[self callTheCallingClass];

}

-(void)CallTheCallingClass
{
 [self.delegate OnFinish];
}
@end

//
@interface mainclass<DownloadProtocol>

@end

@implementation mainclass

-(void)viewDidload
{
Songs *s=[[SOngs alloc]init];
s.delegate=self;
[s download];
}
-(void)OnFinish
{
  NSlog(@"Called");
}
@end

1) видеть, что делегирование осуществляется посредством протокола в объекте c  Я думаю, вы можете понять синтаксис этого...

2) В классе песен мы создаем свойство для этого протокола  мы сохраняем его как ID... bcuz, тип не известен во время компиляции.

3) в классе песен после завершения загрузки мы вызываем метод протокола...

4) В основном классе сначала мы принимаем протокол синтаксис класс выше синтаксис этого

5) мы создаем класс песен

6), затем назначьте основной объект класса (self) делегировать класс композиций

7), то мы должны применить класс протокола в .m добавив имя метода из протокола

8), поэтому отныне всякий раз, когда класс песни вызывает метод протокола через переменную экземпляра делегата.... выход метода protocl для основного класса запускается

попробуйте этот код, надеюсь, что это поможет...

если вам нужна дополнительная информация по этой теме google как шаблон дизайна делегата

основным преимуществом является он способствует слабо связанному программированию...