Ответ 1
Это ключевая концепция, чтобы понять концептуально, поэтому важно, чтобы вы обдумывали, как думать об этом перед техническими деталями. Проще говоря, делегат является обратным вызовом.
Два основных сценария использования делегатов:
- Класс или элемент управления хочет абстрагировать детали о том, как выполнять работу (например, извлекать данные).
- Разрешить другим пользователям перехватывать код в конвейер.
Примеры: UITableView - представление таблицы - это просто элемент управления, который знает, как отображать список ячеек. Он обрабатывает весь тяжелый подъем рендеринга, прокрутки и т.д. Но он не знает, как загрузить ваши данные. Таким образом, вы реализуете делегат datasource, который имеет методы для получения данных ячейки для данной строки и т.д. Это облегчает вам работу. Вы просто используете элемент управления и вставляете специфику своих данных. UITableView сделает все для вас... просто ответьте на несколько конкретных вопросов. Делегат отвечает на несколько конкретных вопросов.
Текстовый контроль - вы добавляете текстовый элемент управления к своему виду и вуаля! вы можете ввести его и все хорошо. Но что делать, если вы хотите что-то сделать, когда набираете текст или когда набираете текст? Ну, текстовое управление предлагает делегату методы, позволяющие подключиться к конвейеру выполнения текстового элемента управления. Это позволяет текстовому управлению делать все для вас и позволяет вставлять код там, где вам это нужно. Много раз, есть способ вставить код, чтобы принять решение о том, разрешено ли что-то. Контроллер перезвонит и спросит, должен ли я сделать x? Вы можете вставлять код и влиять на поведение.
Если вы создаете элемент управления или класс, вы можете создать свой собственный протокол, делегаты datasource и т.д.... поэтому ваш контроль может сосредоточиться на том, что рекламируется. Например, предположим, что вы хотите создать элемент управления задачами. Вы могли:
Сначала создайте контракт. Эй, если вы собираетесь предоставить данные для моего контроля, это вопросы, которые я задам вам. Я возьму это оттуда... В этом случае я собираюсь задать вам количество задач, и я хочу, чтобы вы дали мне задание с номером строки.
@protocol XXTaskBoardDelegate <NSObject>
-(NSInteger*)getTaskCount;
-(XXTask*)getTaskForRow:(NSInteger*)rowNumber;
@end
В элементе управления или классе дайте потребителю способ предоставить нам класс источника данных делегата, который будет отвечать на вопросы, которые задает элемент управления. На данный момент контроль является чистым контролем. Он ничего не знает о том, как вы получаете свои данные. Он запрашивает объект (id), который реализует контракт/протокол. Идентификатор
@implementation XXTaskBoard
- (void)setDelegate:(id<XXTaskBoardDelegate>)newDelegate
{
// the control stores the delegate so it can callback and ask you questions.
}
Затем для класса делегата в объявлении заголовка вы реализуете этот формальный протокол и в файле реализации m вы предоставляете код.
@interface AppController : NSObject<XXTaskBoardDelegate>
{
//...
}
тогда реализуйте его в реализации
@implementation AppController
- (NSInteger*)getTaskCount
{
return [model queryTaskCount];
}
- (XXTask*)getTaskForRow:(NSInteger*)rowNumber
{
return [[model tasks] getItem:(NSInteger*)rowNumber];
}