Обычно обратные вызовы в задаче C выполняются с делегатами. Вот пример реализации пользовательского делегата:
Заголовочный файл:
@interface MyClass : NSObject {
id delegate;
}
- (void)setDelegate:(id)delegate;
- (void)doSomething;
@end
@interface NSObject(MyDelegateMethods)
- (void)myClassWillDoSomething:(MyClass *)myClass;
- (void)myClassDidDoSomething:(MyClass *)myClass;
@end
Файл реализации (.m)
@implementation MyClass
- (void)setDelegate:(id)aDelegate {
delegate = aDelegate; /// Not retained
}
- (void)doSomething {
[delegate myClassWillDoSomething:self];
/* DO SOMETHING */
[delegate myClassDidDoSomething:self];
}
@end
Это иллюстрирует общий подход. Вы создаете категорию на NSObject, которая объявляет имена ваших методов обратного вызова. NSObject на самом деле не реализует эти методы. Этот тип категории называется неформальным протоколом, вы просто говорите, что многие объекты могут реализовывать эти методы. Это способ пересылки объявить тип подписи селектора.
Затем у вас есть некоторый объект, являющийся делегатом «MyClass», и MyClass вызывает соответствующие методы делегата для делегата. Если ваши обратные вызовы делегатов являются необязательными, вы обычно охраняете их на сайте отправки с помощью чего-то вроде «if ([делегат respdsToSelector: @selector (myClassWillDoSomething :)) {». В моем примере делегат требуется для реализации обоих методов.
Вместо неофициального протокола вы также можете использовать формальный протокол, определенный с помощью @protocol. Если вы сделаете это, вы измените тип установщика делегата и переменную экземпляра на «id <MyClassDelegate>
» вместо просто «id
».
Кроме того, вы заметите, что делегат не сохраняется. Обычно это делается потому, что объект, который «владеет» экземплярами «MyClass», как правило, также является делегатом. Если MyClass сохранит свой делегат, то будет цикл сохранения. Хорошая идея в методе dealloc класса, который имеет экземпляр MyClass и является его делегатом для очистки ссылки на этот делегат, поскольку он является слабым обратным указателем. В противном случае, если что-то поддерживает экземпляр MyClass, у вас будет свисающий указатель.