Делегат Objective C является объектом, который был присвоен delegate
свойство другой объект. Для создания один Вы просто определяете класс, который реализует методы делегата, Вы интересуетесь и отмечаете тот класс как реализацию протокола делегата.
, Например, предположите, что Вы имеете UIWebView
. Если требуется реализовать его делегата webViewDidStartLoad:
метод, Вы могли бы создать класс как это:
@interface MyClass
// ...
@end
@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView {
// ...
}
@end
Тогда Вы могли создать экземпляр MyClass и назначить его делегатом веб-представления:
MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;
На UIWebView
сторона, это, вероятно, имеет код, подобный этому, чтобы видеть, отвечает ли делегат webViewDidStartLoad:
сообщение с помощью [1 129] respondsToSelector:
, и отправьте его при необходимости.
if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[self.delegate webViewDidStartLoad:self];
}
само свойство делегата обычно объявляется weak
(в ARC), или assign
(предварительный ARC) для предотвращения сохраняют циклы, так как делегат объекта часто держит сильную ссылку к тому объекту. (Например, контроллер представления часто является делегатом представления, которое он содержит.)
Для определения собственных делегатов необходимо будет объявить их методы где-нибудь, как обсуждено в Документы Apple о протоколах . Вы обычно объявляете формальный протокол. Объявление, перефразируемое от UIWebView.h, было бы похоже на это:
@protocol UIWebViewDelegate
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end
Это походит на интерфейсный или абстрактный базовый класс, поскольку он создает специальный тип для Вашего делегата, UIWebViewDelegate
в этом случае. Конструкторы делегата должны были бы принять этот протокол:
@interface MyClass
// ...
@end
И затем реализуют методы в протоколе. Для методов, объявленных в протоколе как [1 116] (как большинство методов делегата), необходимо свериться -respondsToSelector:
прежде, чем назвать конкретный метод на нем.
Методы делегата обычно называют, начиная с имени класса делегирования и берут объект делегирования в качестве первого параметра. Они также часто используют желание - должен - или сделал - форма. Так, webViewDidStartLoad:
(первый параметр является веб-представлением), а не loadStarted
(берущий параметры), например.
Вместо того, чтобы проверить, отвечает ли делегат на селектор каждый раз, когда мы хотим передать его, можно кэшировать ту информацию, когда делегаты установлены. Один очень очевидный способ, чтобы сделать это должно использовать битовое поле, следующим образом:
@protocol SomethingDelegate
@optional
- (void)something:(id)something didFinishLoadingItem:(id)item;
- (void)something:(id)something didFailWithError:(NSError *)error;
@end
@interface Something : NSObject
@property (nonatomic, weak) id delegate;
@end
@implementation Something {
struct {
unsigned int didFinishLoadingItem:1;
unsigned int didFailWithError:1;
} delegateRespondsTo;
}
@synthesize delegate;
- (void)setDelegate:(id )aDelegate {
if (delegate != aDelegate) {
delegate = aDelegate;
delegateRespondsTo.didFinishLoadingItem = [delegate respondsToSelector:@selector(something:didFinishLoadingItem:)];
delegateRespondsTo.didFailWithError = [delegate respondsToSelector:@selector(something:didFailWithError:)];
}
}
@end
Затем в теле, мы можем проверить, что наш делегат обрабатывает сообщения путем доступа к нашему delegateRespondsTo
структура, а не путем отправки -respondsToSelector:
много раз.
Перед протоколами существовали, было распространено использовать категория на [1 122] для объявления методов, которые мог реализовать делегат. Например, CALayer
все еще делает это:
@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end
Это по существу говорит компилятору, что любой объект мог бы реализовать displayLayer:
.
Вы тогда использовали бы тот же -respondsToSelector:
подход, как описано выше для вызова этого метода. Делегаты просто реализуют этот метод и присваиваются delegate
свойство, и вот именно (нет никакого объявления, что Вы соответствуете протоколу). Эта методика является общепринятой в библиотеках Apple, но новый код должен использовать более современный подход протокола выше, так как этот подход загрязняет NSObject
(который делает автоматическое заполнение менее полезным), и мешает компилятору предупреждать Вас об опечатках и подобных ошибках.
Single namespace: yes. Single module: no.
Your models have to be importable from namespace appname.models
.