2012-05-26 3 views
5

У меня есть класс под названием ToolbarView, который является подклассом UIView и в основном создает UIView, у которого исчезает/вновь появляется UIToolbar сверху. У меня также есть подкласс ToolbarView под названием DraggableToolbarView, который позволяет пользователю перетаскивать представление по экрану.Попытка реализовать делегирование наследования

Мне нужно создать делегат для ToolbarView, чтобы он мог уведомить другой объект/класс о том, когда панель инструментов снова появляется и исчезает. Мне также нужно создать делегат для DraggableToolbarView, чтобы я мог уведомить другой объект/класс, когда перетаскивается представление. Делегат DraggableToolbarViews также должен уведомлять другой объект/класс о том, когда панель инструментов снова появляется и исчезает.

Так что я решил реализовать ToolbarViewDelegate, и DraggableToolbarViewDelegate наследуют от него и иметь свой собственный метод, как следующий:

ToolbarView.h

#import <UIKit/UIKit.h> 

@protocol ToolbarViewDelegate; 

@interface ToolbarView : UIView <UIGestureRecognizerDelegate> 
{ 
    id <ToolbarViewDelegate> _toolbarViewDelegate; 
} 

@property(nonatomic, assign) id <ToolbarViewDelegate> toolbarViewDelegate; 

@end 

ToolbarView.m

#import "ToolbarView.h" 
#import "ToolbarViewDelegate.h" 

... 

- (void) showBars 
{  
     ... 
     if (self.toolbarViewDelegate) 
     { 
      [self.toolbarViewDelegate toolbarViewWillShowToolbar:self]; 
     } 

     ... 
} 

- (void) hideBars 
{ 
     ... 
     if (self.toolbarViewDelegate) 
     { 
      [self.toolbarViewDelegate toolbarViewWillHideToolbar:self]; 
     } 

     ... 
} 

К olbarViewDelegate.h

@class ToolbarView; 

@protocol ToolbarViewDelegate 

@required 

- (void) toolBarViewWillShowToolbar:(ToolbarView *)toolbarView; 
- (void) toolBarViewWillHideToolbar:(ToolbarView *)toolbarView; 

@end 

DraggableToolbarView.h

#import "ToolbarView.h"

@protocol DraggableToolbarViewDelegate; 

@interface DraggableToolbarView : ToolbarView 
{ 
    id <DraggableToolbarViewDelegate> _draggableToolbarViewDelegate; 
} 

@property(nonatomic, assign) id <DraggableToolbarViewDelegate> draggableToolbarViewDelegate; 

@end 

DraggableToolbarView.m

#import "DraggableToolbarView.h" 
#import "DraggableToolbarViewDelegate.h" 

... 

- (void)drag:(UIPanGestureRecognizer *)sender 
{ 
    ... 
     if (self.draggableToolbarViewDelegate) 
     { 
      [self.draggableToolbarViewDelegate draggableToolbarViewWillDrag:self]; 
     } 

    ... 

} 

... 

DraggableToolbarViewDelegate.h

#import "ToolbarViewDelegate.h" 

@class DraggableToolbarView; 

@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate> 

@required 

- (void) draggableToolbarViewWillDrag:(DraggableToolbarView *)draggableToolbarView; 

@end 

SomeViewController.h

#import <UIKit/UIKit.h> 
#import "ToolbarViewDelegate.h" 
#import "DraggableToolbarViewDelegate.h" 

@interface SomeViewController : UIViewController <ToolbarViewDelegate, DraggableToolbarViewDelegate> 
{ 

} 
@end 

SomeViewController.m

#import "DraggableToolbarView.h" 
... 
- (void) toolbarViewWillShowToolbar:(ToolbarView*)toolbarView 
{ 
    //NSLog(@"Toolbar Showed"); 
} 

- (void) toolbarViewWillHideToolbar:(ToolbarView*)toolbarView 
{ 
    //NSLog(@"Toolbar Hidden"); 
} 

- (void) draggableToolbarViewWillDrag:(DraggableToolbarView*)draggableToolbarView 
{ 
    //NSLog(@"Dragged"); 
} 

... 

[draggableToolbarView setDraggableToolbarViewDelegate:self]; 

... 

Когда я делаю это только DraggableToolbarDelegate методы реагирования. Однако, когда я также делаю [drabbleToolbarView setToolbarViewDelegate:self], он работает. Я пробовал делать каждый делегат отдельно без наследования, и он отлично работает, поэтому я считаю, что проблема не в какой-либо другой части кода.

Кто-нибудь может знать, почему? Я понял, что наследование протоколов наследует, мне также не нужно будет устанавливать ToolbarViewDelegate для объекта DraggableToolbar.

UPDATE: Добавлено много больше кода

ответ

6

В своем коде, любой DraggableToolbarView экземпляр имеет два свойства для подключения делегатов, один называется toolbarViewDelegate, которые он наследует от своего родительского класса, и один называется draggableToolbarViewDelegate, который определен в DraggableToolbarView себя. Вы должны установить оба из них, если вы хотите, чтобы контроллер получил все сообщения делегата.

Возможно, вы пытаетесь сделать это. Вы должны использовать одно и то же имя свойства в обоих классах просмотра, так что для любого экземпляра есть только одно соединение с делегатом.

Сначала измените имя делегата в суперклассе. (Обратите внимание, что вам не нужно, да и не должно беспокоить, чтобы объявить Ивар за собственность - это созданный @synthesize.)

@interface ToolbarView : UIView <UIGestureRecognizerDelegate> 
@property (nonatomic, assign) id <ToolbarViewDelegate> delegate; 
@end 

Вы будете использовать то же имя свойства в подклассе.

@interface DraggableToolbarView : ToolbarView 
@property (nonatomic, assign) id <DraggableToolbarViewDelegate> delegate; 
@end 

Это допускается до тех пор, как имя основы Ивара в подклассе отличается, чем у суперкласса, например,

// In superclass 
@synthesize delegate; 
// In subclass 
@synthesize delegate = delegate_; 

Теперь все изменения делегата сообщений в двух классов представлений использовать это одно свойство:

- (void)showBars 
{ 

    if (self.delegate) 
    { 
     [self.delegate ... 

- (void)drag:(UIPanGestureRecognizer *)sender 
{ 
    //... 
    if (self.delegate) 
    { 
     [self.delegate ... 

Теперь вы можете отправить setDelegate: к DraggableToolbarView и он будет использовать один и тот же делегат для перетаскивания методов и т он показывает/скрывает методы.

И наконец, терминология/пояснительная записка. В ответ на your previous question Калеб использовал правильный термин для «сложенных» протоколов, а Ричард не сделал этого. Протоколы не наследуют друг от друга, но один протокол может принять другой. Отношения аналогичны, но различны. Когда объект соответствует протоколу, он обещает реализовать методы, объявленные в этом протоколе. Никакой реализации не идет вместе с протоколом. То же самое относится к одному протоколу, принимающему другое - методы только что объявлены в обоих.Когда вы пишете:

@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate> 

вы говорите, что любой объект, который обещает реализовать методы DraggableToolbarViewDelegate «s также реализовать методы из ToolbarViewDelegate. Это все, что это значит. Опять же, никакая реализация не приходит вместе с этим обещанием.

В этом случае это означает, что DraggableToolbarView может ожидать, что его делегат будет реализовывать методы в ToolbarViewDelegate.

+0

Цените это замечательное сообщение. Думаю, я могу просто придерживаться отдельных делегатов, а не большого поклонника именования. Что вы обычно делаете или рекомендуете делать? –

+0

Рад, что я мог помочь. Я не вижу ничего плохого в переопределении собственности делегата; это делает обе стороны кода чище. –

1

Вы не дали весь код, но от того, что находится здесь, Убедитесь, что

  1. Ваш ToolBarView и его подклассы имеют id <ToolBarViewDelegate> делегат, как недвижимость.
  2. Ваш DraggableToolbarViewDelegate расширяет протокол NSObject.
  3. и ваш другой объект ViewController соответствует протоколу делегирования, а не панели инструментов.
  4. Как только ваш контроллер реализует методы делегатов и соответствует протоколу, установите для объекта делегата объект self, а затем используйте свойство delegate, установленное в представлении, для вызова этих методов протокола.
Смежные вопросы