Что такое протоколы и делегаты и как они используются в IOS? - программирование
Подтвердить что ты не робот

Что такое протоколы и делегаты и как они используются в IOS?

Я действительно смущен концепцией делегатов и протоколов. Являются ли они эквивалентными интерфейсам и классам адаптеров в Java? Как они работают? Ни один из ресурсов, которые я прочитал, пока не был полезен. "Делегирование - это простой и мощный шаблон, в котором один объект в программе действует от имени или по согласованию с другим объектом. Делегирующий объект сохраняет ссылку на другой объект - делегат - и в соответствующее время отправляет сообщение к нему". Я без понятия что это значит. Может кто-нибудь объяснить, что это такое и дать простой пример? Спасибо заранее!

ИЗМЕНИТЬ:

Насколько я понимаю,

1) делегаты реализуют протоколы (другое имя для интерфейсов)

2) объект регистрирует делегат (который реализует протокол)

3) объект может вызывать методы протокола для делегата

Следовательно, делегат соединяет объект с протоколом.

Пожалуйста, поправьте меня, если я ошибаюсь.

Я все еще не понимаю, почему сам объект не может реализовать протокол? Это могло быть намного проще!

4b9b3361

Ответ 1

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

Вы указываете протокол таким образом:

@protocol MyProtocol <NSObject>

- (void)aRequiredMethod;

@required
- (void)anotherRequiredMethod;

@optional
- (void)anOptionalMethod;

@end

Способы, объявленные после @required или перед любым другим спецификатором, требуются, и классы, которые хотят использовать ваш протокол, должны реализовать все из них. Вы также можете объявить некоторые необязательные методы, объявив их после спецификатора @optional.

Затем вы можете указать, что класс "соответствует" протоколу (реализует необходимые методы) в интерфейсе класса:

@interface MyClass <MyProtocol>

@end

Обычно вы ссылаетесь на объект, соответствующий протоколу с использованием свойства. Например, чтобы отслеживать делегат:

@property (nonatomic, weak) id<MyProtocol> delegate;

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

[self.delegate aRequiredMethod];

Чтобы проверить, соответствует ли объект протоколу, вы можете вызвать

[self.delegate conformsToProtocol:@protocol(MyProtocol)]

Чтобы проверить, что объект реализует метод, вы можете вызвать

[self.delegate respondsToSelector:@selector(anOptionalMethod)]

Для получения дополнительной информации ознакомьтесь с руководством Apple Работа с протоколами.

Ответ 2

Протокол, объявленный с помощью (@protocol syntax in Objective-C), используется для объявления набора методов, которые реализует класс, который "принимает" (объявляет, что он будет использовать этот протокол). Это означает, что вы можете указать в своем коде, что "вам не важно, какой класс используется, пока он реализует конкретный протокол". Это можно сделать в Objective-C следующим образом:

id<MyProtocol> instanceOfClassThatImplementsMyProtocol;

Если вы укажете это в своем коде, то любой класс, который "соответствует" протоколу MyProtocol, может использоваться в переменной instanceOfClassThatImplementsMyProtocol. Это означает, что код, который использует эту переменную, знает, что он может использовать любые методы, определенные в MyProtocol с этой конкретной переменной, независимо от того, какой класс он есть. Это отличный способ избежать шаблона проектирования наследования и избежать жесткой связи.

Делегаты используют языковые возможности протоколов. Схема проектирования делегаций - это способ разработки вашего кода для использования протоколов там, где это необходимо. В рамках Cocoa шаблон проектирования делегата используется для указания экземпляра класса, который соответствует определенному протоколу. Этот конкретный протокол определяет методы, которые должен реализовать класс делегата для выполнения определенных действий в данных событиях. Класс, который использует делегат, знает, что его делегат соответствует протоколу, поэтому он знает, что он может вызывать реализованные методы в заданное время. Этот шаблон проектирования - отличный способ развязать классы, потому что он действительно упрощает обмен одним экземпляром делегата для другого - все, что должен сделать программист, - обеспечить, чтобы экземпляр или класс замены соответствовал требуемому протоколу (то есть он реализует методы, указанные в протоколе)!

Протоколы и делегаты не ограничиваются только Objective-C и Mac/iOS, но язык Objective-C и каркасы Apple сильно используют эту удивительную языковую особенность и шаблон дизайна.

Edit:

Пожалуйста, найдите этот пример. В UIKit framework для Cocoa Touch есть протокол UITextFieldDelegate. Этот протокол определяет ряд методов, которые должны реализовывать классы, которые являются делегатами экземпляра UITextField. Другими словами, если вы хотите назначить делегата UITextField (используя свойство delegate), лучше убедиться, что этот класс соответствует UITextFieldDelegate. Фактически, поскольку свойство делегата UITextField определяется как:

@property(nonatomic, assign) id<UITextFieldDelegate> delegate

Затем компилятор выдаст предупреждения, если вы присвоите ему класс, который не реализует протокол. Это действительно полезно. Вы должны заявить, что класс реализует протокол, и, говоря, что это так, вы позволяете другим классам знать, что они могут взаимодействовать определенным образом с вашим классом. Таким образом, если вы назначаете экземпляр MyTextFieldDelegateClass для свойства делегата UITextField, UITextField знает, что он может вызывать определенные методы (связанные с вводом текста, выбором и т.д.) Вашего MyTextFieldDelegateClass. Он знает это, потому что MyTextFieldDelegateClass сказал, что будет реализовывать протокол UITextFieldDelegate.

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

Ответ 3

В этом простейшем виде делегат - это объект, который получает сообщения от другого объекта. И вы делаете это все время.

Так скажите, что у вас был автомобиль с двигателем.

@interface car : NSObject

@property (nonatomic) id engine;

@end

Таким образом, можно переслать начальное сообщение в движок.

[_engine start];

Двигатель действует как делегат, вы просто передаете ему сообщение.

Протоколы делают его более формальным, и Xcode проверяет, соответствуют ли вам требуемые или необязательные методы.

@property (nonatomic) id <engineDelegate> engine;

говорит, что объект engine ДОЛЖЕН содержать запуск функции, потому что в определении протокола он запросил его.

@protocol engineDelegate 
 - (void) start;
@optional
 - (double) fuelLevel;
@end

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

@interface timeWarpDrive : NSObject <engineDelegate>