Может ли кто-нибудь сказать мне разницу между
@property (nonatomic, weak) id delegate;
@property (nonatomic, weak) id <protocol_name> delegate;
@property (nonatomic, weak) UIViewController * <protocol_name> delegate;
Может ли кто-нибудь сказать мне разницу между
@property (nonatomic, weak) id delegate;
@property (nonatomic, weak) id <protocol_name> delegate;
@property (nonatomic, weak) UIViewController * <protocol_name> delegate;
@property (nonatomic, weak) id delegate;
Это указывает, что объекты текущего класса имеют делегат, который может быть любого типа. Спецификатор weak
является общим для объектов делегата, так как это означает, что объект с делегатом не увеличивает счетчик ссылок делегата (в ARC-talk "держите ссылку на него" ). A weak
ссылка для делегата - стандартная практика.
@property (nonatomic, weak) id < protocol_name > delegate;
Это указывает, что объекты текущего класса имеют делегат, который может быть любого типа (id), но должен соответствовать протоколу protocol_name
. Это особенно полезно, поскольку класс, содержащий делегата, знает, что есть определенные сообщения, которые он может отправить своему делегату, и "знать", что делегат будет отвечать на них.
@property (nonatomic, weak) UIViewController * < protocol_name > delegate;
Это то же самое, что и второй пример, за исключением того, что делегат должен быть объектом класса UIViewController
. На практике объекты delegate
обычно имеют тип id
, хотя это не является обязательным требованием - он просто предоставляет большую свободу программисту.
РЕДАКТИРОВАТЬ: Протоколы
Скажем, вы объявляете класс следующим образом:
@interface MyObject : NSObject <MyDelegateProtocol>
// ...
@end
<MyDelegateProtocol>
в этом объявлении означает, что MyObject
реализует методы, определенные в протоколе MyDelegateProtocol
(т.е. "соответствует протоколу" ).
Определение протокола (до определения класса, очевидно) может выглядеть так:
@protocol MyDelegateProtocol <NSObject>
@required
- (void)method1;
- (void)method2;
@optional
- (void)method3;
@end
Это означает, что любой объект, "соответствующий" протоколу MyDelegateProtocol
, должен реализовывать методы, называемые -(void)method1
и -(void)method2
. И, необязательно, может включать реализацию для сообщения -(void)method3
.
Это чрезвычайно полезная информация для объектов-делегатов (имя протокола может быть любым, кстати, я просто включаю слово "делегат", чтобы было очевидно, что он используется в качестве протокола делегата).
Если теперь определяет другой класс:
@property (nonatomic, weak) id<MyDelegateProtocol> delegate;
класс знает, что он может полагаться на реализации -method1
и -method2
, которые будут реализованы его делегатом, и -method3
также может быть реализован (что он может проверить с помощью кода таких как:)
if ([self.delegate respondsToSelector:@selector(method3)]) {
[self.delegate method3];
}
else {
// Delegate doesn't implement -method3.
}
Проверка не нужна для -method1
и -method2
, поскольку эти методы @required
определяют определение протокола и могут вызывать их, когда захотят.
Класс может также использовать более одного протокола за раз (например, <Proto1, Proto2, UITableViewDelegate>
) - для более полного обзора протоколов, Apple Docs on протоколы.
@property (неатомный, слабый) id делегат;
Свойство без определенного типа или реализации протокола. При вызове методов на delegate
все идет - компилятор будет доверять вам, если он увидит, что метод существует где-то, и время выполнения проверяет, лежали ли вы.
@property (неатомный, слабый) id < имя_файлa > делегат;
Свойство без определенного типа, но которое реализует указанный протокол. Вы можете вызывать только методы из этого протокола (если только вы не выполняете кастинг). Любой экземпляр, который установлен в свойство, должен соответствовать протоколу (или, опять же, вам нужно какое-то литье).
@property (неатомный, слабый) UIViewController * < имя_файлa > делегат;
Свойство с определенным типом (UIViewController
) и которое реализует указанный протокол. Вы можете вызывать только методы из этого протокола и из класса UIViewController
(если только вы не выполняете кастинг). Любой экземпляр, который установлен в свойство, должен соответствовать протоколу и быть подклассом UIViewController
(или, опять же, вам нужно некоторое литье).
В первом примере:
@property (nonatomic, weak) id delegate;
вы создаете свойство типа id, которое является "любым" типом в объекте c с именем - делегатом.
Второй пример:
@property (nonatomic, weak) id < protocol_name > delegate;
создается свойство идентификатора типа, которое должно соответствовать протоколу protocol_name с именем - delegate.
Последний пример:
@property (nonatomic, weak) UIViewController * < protocol_name > delegate;
вы создаете свойство типа UIViewController (указатель на UIViewController), который должен соответствовать протоколу protocol_name с именем-delegate.