Как расширить протоколы/делегаты в Objective-C
Если я хочу расширить класс, подобный AVAudioPlayer, лучший способ добавить еще один метод в AVAudioPlayerDelegate?. Я могу создать для него категорию, продлить ее? Если я его продюсирую, я также должен обязательно перезаписать фактический получатель/сеттер делегата? Как продлить протокол? Ниже приводятся ошибки
@protocol AudioTrackDelegate : AVAudioPlayerDelegate {
- (void)foo;
}
@end
@interface AudioTrack : AVAudioPlayer {
}
@end
Ответы
Ответ 1
Синтаксис для создания протокола, который реализует другой протокол, таков:
@protocol NewProtocol <OldProtocol>
- (void)foo;
@end
Если вы хотите вызвать метод в NewProtocol
на указателе, набранном как OldProtocol
, вы можете вызвать respondsToSelector
:
if ([object respondsToSelector:@selector(foo)])
[(id)object foo];
Или определите методы заглушки как категории на NSObject
:
@interface NSObject (NewProtocol)
- (void)foo;
@end
@implementation NSObject (NewProtocol)
- (void)foo
{
}
@end
Ответ 2
Помните, что протокол не добавляет код в скомпилированное приложение - он только подтверждает тот факт, что ваш класс должен реализовать методы, которые считаются "соответствующими" протоколу. Хорошим использованием этого было бы создание группы классов со всем тем же способом: <printable>
или <serialized>
и т.д. Таким образом, вы могли бы создать протокол <plays>
, например:
@protocol plays
- (void) play;
- (NSString *) type;
@end
И тогда класс, соответствующий <plays>
, должен реализовывать методы play
и type
. Если это не так, компилятор выдает предупреждение, но в любом случае компилирует класс. В коде вы проверяете соответствие объекта протоколу со следующим кодом:
if ([obj conformsTo: @protocol(plays)]) {
[obj play];
}
Категория фактически добавляет новые методы динамически в ваш класс. Эти методы глобально доступны для среды выполнения как селекторы и могут быть вызваны по имени, как в @selector(foo)
и [object foo:bar];
Целью категории является добавление специального класса в класс, даже если у вас нет исходного кода для этого класса. Там могут быть проблемы с безопасностью, и вы можете создавать утечки памяти в классах и т.д.
В вашем случае, может быть, в отдельном файле AVAudioPlayerDelegate_TrackOps.m
#import "AVAudioPlayerDelegate.h"
@implementation AVAudioPlayerDelegate (TrackOps)
- (NSObject *) foo {
// do foo stuff;
return bar;
}
@end
Помещая его как категорию NSObject
, все классы отвечают на foo
. foo
может быть автономным методом Objc_perform_selector(@selector(foo))
.
Bottom Line: используйте категорию, чтобы добавить быстрый метод к классу, протоколы для обеспечения соблюдения
методы реализации и подклассы для специализации существующих классов (например, добавления переменных-членов или основных новых функций). Категории также могут использоваться для переопределения метода или двух, когда подкласс не нужен и не нужен, но обычно, если вы хотите добавить функциональность в класс, вы создаете подкласс. Для более примеров, идей, другой общей информации по этой теме всегда есть Введение Apple в Objective-C