Немного смущает делегатов в Objective-C

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

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

Кто-нибудь заботится о разработке?

Спасибо!

Ответ 1

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

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

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

  • Условно перед - Сигналы что-то произойдет, но делегат может прервать. Имя всегда включает слово Should.
    Пример: searchBar Should EndEditing:.
  • Безусловно раньше - Сигналы что-то произойдет. Имя всегда включает слово. Пример: application Will Terminate:.
  • Безоговорочно после - сигналы что-то произошло. Имя всегда включает слово. Пример: application Did FinishLaunching:.
  • Настройщики. Запросите информацию о том, как работать. Имя включает информацию, которая требуется.
    Пример tableView: viewForHeaderInSection :.

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

Ответ 2

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

Чтобы класс был делегатом, вы должны объявить его как таковой. В приведенном выше примере скажем, что у вас есть объект 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 очень, очень хороши, и все протоколы делегатов довольно понятны.

Ответ 3

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

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

[delegate tableView:self didSelectRowAtIndexPath:indexPath];

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

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

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

Ответ 4

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

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

Вы используете систему делегатов, когда хотите, чтобы объект выполнял код из отдельного класса. Например, как описано здесь, когда вы нажмете 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. И он получает помощь от этих иностранных классов в соответствии со своими протокольными методами, , определяя себя как соответствующие тем, и импортирует любые необходимые файлы заголовков для использования этих методов.

Ответ 5

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

Ответ 6

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