Несколько делегатов на один объект?
У меня есть UIScrollView
, который мне нужен для подкласса, и внутри подкласса мне нужно прикрепить UIScrollViewDelegate
, чтобы я мог реализовать метод viewForZoomingInScrollView
.
Тогда у меня есть UIViewController
, где мне нужно создать экземпляр объекта этого UIScrollView
подкласса, который я создал, и я также хотел бы сделать UIViewController UIScrollViewDelegate
для этого объекта, чтобы я мог реализовать scrollViewDidZoom
в этом UIViewController
классе.
Как можно сделать так, чтобы у одного объекта было два делегата? (Я знаю, что легко мог бы иметь только одного делегата и просто реализуйте оба метода там, но для целей дизайна я хотел бы сделать это так, как я упоминаю).
3 ответа:
Вам не нужен объект с 2 делегатами. Вы хотите, чтобы ваш customScrollView сохранял ответственность за свои собственные функции UIScrollViewDelegate.
Чтобы заставить parentVC реагировать на методы делегирования UIScrollView, вам придется создать пользовательский делегат внутри вашего customScrollView.
В момент вызова функции UIScrollViewDelegate вы также вызовете одну из своих функций делегата из пользовательского делегата. Таким образом, ваш parentVC будет реагировать в данный момент Вы этого хотите.
Это будет выглядеть примерно так.
CustomScrollView.h
@protocol CustomDelegate <NSObject> //custom delegate methods -(void)myCustomDelegateMethod; @end @interface CustomScrollView : UIScrollView <UIScrollViewDelegate> { id<CustomDelegate> delegate //the rest of the stuff
CustomScrollView.m
-(void) viewForZoomingInScrollView { [self.delegate myCustomDelegateMethod]; //rest of viewForZoomingInScrollView code
ParentVC.h
@interface CustomScrollView : UIViewController <CustomDelegate> { //stuff
ParentVC.m
-(void)makeCustomScrollView { CustomScrollView *csv = [[CustomScrollView alloc] init]; csv.delegate = self; //other stuff } -(void)myCustomDelegateMethod { //respond to viewForZoomingInScrollView }
Я надеюсь, что это полностью покрывает вашу проблему. Удачи.
Иногда имеет смысл присоединить несколько делегатов к виду прокрутки. В этом случае можно построить простой разделитель делегирования:
// Public interface @interface CCDelegateSplitter : NSObject - (void) addDelegate: (id) delegate; - (void) addDelegates: (NSArray*) delegates; @end // Private interface @interface CCDelegateSplitter () @property(strong) NSMutableSet *delegates; @end @implementation CCDelegateSplitter - (id) init { self = [super init]; _delegates = [NSMutableSet set]; return self; } - (void) addDelegate: (id) delegate { [_delegates addObject:delegate]; } - (void) addDelegates: (NSArray*) delegates { [_delegates addObjectsFromArray:delegates]; } - (void) forwardInvocation: (NSInvocation*) invocation { for (id delegate in _delegates) { [invocation invokeWithTarget:delegate]; } } - (NSMethodSignature*) methodSignatureForSelector: (SEL) selector { NSMethodSignature *our = [super methodSignatureForSelector:selector]; NSMethodSignature *delegated = [(NSObject *)[_delegates anyObject] methodSignatureForSelector:selector]; return our ? our : delegated; } - (BOOL) respondsToSelector: (SEL) selector { return [[_delegates anyObject] respondsToSelector:selector]; } @end
Затем просто установите экземпляр этого разделителя в качестве делегата представления прокрутки и присоедините любое число делегатов к разделителю. Все они примут участие в мероприятиях делегации. Некоторые предостережения применимы, например, предполагается, что все делегаты имеют один и тот же тип, иначе у вас возникнут проблемы с наивной реализацией
respondsToSelector
. Это не большая проблема, легко изменить реализацию, чтобы отправлять события делегирования только тем, кто их поддерживает.
Краткий ответ: Нет. делегаты, как правило, являются слабыми отношениями один-к-одному:
@property (nonatomic, weak /*or assign*/) id<MyViewDelegate> delegate;
Иногда вы увидите шаблон дизайна "слушатель", который является формой делегатов один ко многим:
- (void) addListener:(id<MyViewListener>)listener; - (void) removeListener:(id<MyViewListener>)listener;
В вашем случае в UIScrollView нет хорошей точки публичного переопределения, которая позволяет подклассам указывать viewForZoomingInScrollView. Я бы не стал делать UIScrollView своим собственным делегатом, если это возможно. Вы могли бы сделать UIViewController UIScrollViewDelegate и заставить его предоставить