Немного смущает делегатов в Objective-C - PullRequest
12 голосов
/ 29 августа 2009

Я знаю немного о Objective-C, и я работаю над книгой для iPhone SDK (из книги Obj-C, которая только что делала консольные программы). Он пытался объяснить делегатам, хотя был поспешен и не понимал, что он пытается передать. Я немного запутался в том, что они из себя представляют и когда вы их используете.

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

Кто-нибудь хочет уточнить?

Спасибо!

Ответы [ 6 ]

20 голосов
/ 29 августа 2009

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

Какао делает обратное; вместо этого экземпляры запрашивают данные, когда и если они необходимы.

Существует четыре основных типа методов делегата:

  • Условно до - Сигнализирует, что что-то должно произойти, но делегат может прерваться. Имя всегда включает слово Следует.
    Пример: searchBarShouldEndEditing:.
  • Безусловно, до - сигнализирует о том, что что-то должно произойти. Имя всегда включает слово воля.
    Пример: applicationWillTerminate:.
  • Безоговорочно после - Сигналы что-то случилось. Имя всегда включает слово сделал.
    Пример: applicationDidFinishLaunching:.
  • Настройщики - Запрос информации о том, как функционировать. Имя включает в себя информацию, которая требуется.
    Пример tableView:viewForHeaderInSection:.

Все методы-делегаты всегда имеют своего отправителя в качестве одного из аргументов. Любой метод делегата может иметь возвращаемое значение, которое изменяет поведение отправителя.

7 голосов
/ 29 августа 2009

Допустим, вы хотите предоставить пользователю предупреждение и хотите, чтобы метод запускался, когда пользователь касается одной из кнопок. Проблема в том, как узнать, какой метод вызывать, к какому объекту, когда кто-то касается кнопки?

Чтобы класс был делегатом, вы должны объявить его таковым. В приведенном выше примере предположим, что у вас есть объект ApplicationController, который управляет потоком вашего приложения. В декларации мы сказали бы

@interface ApplicationController : NSObject <UIAlertViewDelegate>

Это сообщает компилятору, что ApplicationController собирается реализовать некоторые методы в протоколе UIAlertViewDelegate. Мы смотрим этот протокол в нашей документации и видим список методов. Поскольку мы хотим что-то сделать при нажатии кнопки, мы видим:

alertView:clickedButtonAtIndex: - отправляется делегату, когда пользователь нажимает кнопку в представлении предупреждений. Этот метод не является обязательным.

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

Итак, если мы реализуем метод в ApplicationController с именем alertView:clickedButtonAtIndex, создаем объект ApplicationController, а затем устанавливаем этот объект как делегат оповещения, которое мы показываем, все настроено. Как только кто-то нажимает кнопку в предупреждении, будет вызван метод alertView:clickedButtonAtIndex, передавая представление alertView и индекс нажатой кнопки.

Это позволяет вам делать с этой информацией все, что вы хотите. Простое утверждение дела:

if( buttonIndex == 0 ) {
    _myString = @"Pressed the button";
} else {
    _myString = @"Pressed the other button";
}

Справочные документы Objective-C очень, очень хороши, и все протоколы делегатов говорят сами за себя.

6 голосов
/ 29 августа 2009

Хороший способ понять делегатов - это через пример. Одним из примеров является UITableView (или NSTableView, в зависимости от того, говорим ли мы об iPhone или Mac OS). В любом случае, табличное представление имеет delegate и dataSource (оба они действуют как вспомогательные объекты для получателя).

Вместо UITableView обработки событий, когда, например, пользователь касается одной из его строк, он вместо этого сообщает delegate "Эй! Я постучал в эту строку и в этом разделе, что делать ты сможешь!". Обычно delegate - это какой-то Контроллер, который реализует правильный метод. Таким образом, табличное представление (после проверки, действительно ли у delegate есть определение для метода) отправляет сообщение, подобное этому:

[delegate tableView:self didSelectRowAtIndexPath:indexPath];

Поскольку ваш контроллер является делегатом таблицы и реализует этот метод, он решает, что делать. Когда метод завершается (в этом случае он должен просто вернуть void), выполнение продолжается в табличном представлении.

Делегаты - это концепция. Это не языковая особенность Objective-C. Элемент delegate в UITableView похож на любой другой объект. Хотя делегаты, как правило, не сохраняются, они вместо этого назначаются (чтобы избежать retain циклов).

Они очень удобны, когда вы их освоили. Я предлагаю потренироваться с примерами, такими как TableViews (NSTableView, как я уже говорил ранее, работает аналогичным образом, только с разными методами).

2 голосов
/ 04 октября 2013

Делегат (что означает представитель ) - это класс (объект), который также хочет представлять (наследовать) другой не связанный класс. Объект делегата может наследовать от другого несвязанного класса, «соответствуя» (имея несколько реализаций) требуемым методам протокола несвязанного класса, которые указывают стороннему классу, что этот объект теперь способен соответствующим образом передавать свою основную информацию.

Вы используете наследование , когда хотите, чтобы связанные классы обменивались методами. Вы используете делегатов , когда хотите, чтобы несвязанные классы совместно использовали методы. Подход делегата позволяет объекту от одного класса наследовать методы от иначе несвязанного класса. «Объект делегата» или «представительский объект» - это объект, который наследуется от чужого класса; он обозначается как представитель, делегат этого удаленного класса, поэтому при назначении объекта в качестве делегата классу вы даете ему разрешение также представлять этот класс, даже если он обычно не наследуется от этого класса. , (Если он унаследован от класса, вам не нужно устанавливать его в качестве делегата этого класса; у него уже будет доступ к методам класса. Но вы хотите, чтобы этот несвязанный объект наследовал некоторые методы из класса, представляя класс, и возвращая некоторую информацию обратно в класс отправителя, так что вы делаете его представителем-делегатом этого класса, даже если он наследует от другого набора классов.) Это по существу позволяет одному несвязанному классу наследовать от другого несвязанного класса, но с минимум осложнений к его основной линии наследования.

Вы используете систему делегатов, когда хотите, чтобы объект выполнял код из отдельного класса. Например, , как описано здесь , когда вы нажимаете Enter в текстовом поле, текстовое поле на самом деле не знает, что делать с этой информацией. Он просматривает класс своего объекта делегата (например, контроллер окна документа или документ) и использует соответствующий метод этого класса, который соответствует соответствующему методу текстового поля, найденному в протоколе делегата его текстового поля, что-то вроде textFieldShouldReturn. Таким образом, в этом случае вы устанавливаете контроллер окна или документ в качестве делегата текстового поля, потому что текстовое поле нуждается в этом классе для представления информации, которую оно было предоставлено.

Классу A нужен метод из класса B, но класс A не наследуется от класса B. Сначала скажите компилятору, что класс A соответствует протоколу класса B:

@interface ClassA : NSObject <ClassBDelegateProtocol>

В документации Apple каждая ссылка на класс отображается вверху: «Наследуется от» и «Соответствует». Например, NSDocumentController наследуется от NSObject и соответствует NSUserInterfaceValidations, NSCoding и NSObject(NSObject). Соответствие NSCoding взято из объявления интерфейса в NSDocumentController.h

@interface NSDocumentController : NSObject <NSCoding>

и NSUserInterfaceValidations из объявления метода в NSDocumentController.h

-(BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item;

вместе с #import

#import <AppKit/NSUserInterfaceValidation.h>

Таким образом, тогда как NSDocumentController наследуется от NSObject, , он также нуждается в некоторой помощи от NSCoding и NSUserInterfaceValidation. И он получает помощь от этих внешних классов, в соответствии с их методами протокола , , определяющими себя как соответствующие этим методам , и , импортирующими любые необходимые заголовочные файлы для использования этих методов .

0 голосов
/ 23 октября 2016

Вы не одиноки, я все еще учусь этому сам. Я думаю, что лучше, если я попытаюсь объяснить это словами, а не кодом. Существует протокол, который содержит определенный метод или действие, которое вы хотите выполнить. Делегат берет метод из протокола, поэтому может использовать его для облегчения действия или метода. Я нашел эту статью очень полезной http://rypress.com/tutorials/objective-c/protocols. Надеюсь, это поможет.

0 голосов
/ 29 августа 2009

Взгляните на мое руководство по шаблону проектирования делегатов здесь: http://www.jonmsterling.com/blog/?p=74. Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...