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

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

EDIT:

насколько я теперь понимаю,

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

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

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

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

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

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

3 ответов


протоколы-это способ указать набор методов, которые должен реализовать класс, если он хочет работать с одним из ваших классов. Делегаты и источники данных, такие как 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 Работа С Протоколами.


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

id<MyProtocol> instanceOfClassThatImplementsMyProtocol;

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

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

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

Edit:

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

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

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

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


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

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

@interface car : NSObject

@property (nonatomic) id engine;

@end

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

[_engine start];

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

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

@property (nonatomic) id <engineDelegate> engine;

говорит, что объект engine должен содержать функцию start, потому что в определении протокола он попросил ее.

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

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

@interface timeWarpDrive : NSObject <engineDelegate>