2012-05-26 7 views
5

Mam klasę o nazwie ToolbarView, która jest podklasą UIView i zasadniczo tworzy UIView, który ma znikanie/ponowne pojawianie się paska UIToolbar na wierzchu. Mam również podklasę ToolbarView o nazwie DraggableToolbarView umożliwia użytkownikowi przeciągnięcie widoku wokół ekranu.Próba implementacji dziedziczenia delegata

Potrzebuję utworzyć delegata dla ToolbarView, aby mógł powiadomić inny obiekt/klasę, gdy pasek narzędzi pojawi się ponownie i zniknie. Muszę również utworzyć delegata dla DraggableToolbarView, aby móc powiadomić inny obiekt/klasę, gdy widok jest przeciągany. Delegat DraggableToolbarViews będzie również musiał powiadomić inny obiekt/klasę, gdy pasek narzędzi pojawi się ponownie i zniknie.

Więc postanowiłem realizować ToolbarViewDelegate, i DraggableToolbarViewDelegate dziedziczą z niego i ma swoją własną metodę jak następuje:

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]; 
     } 

     ... 
} 

Toolb arViewDelegate.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]; 

... 

Kiedy to zrobić tylko metody DraggableToolbarDelegate reagują. Jednak gdy robię też [drabbleToolbarView setToolbarViewDelegate:self], to działa. Próbowałem robić każdego delegata osobno bez dziedziczenia i działa dobrze, więc uważam, że problem nie występuje w żadnej innej części kodu.

Ktoś może wiedzieć dlaczego? Pomyślałem, że poprzez dziedziczenie protokołów, nie musiałbym ustawiać ToolbarViewDelegate dla obiektu DraggableToolbar.

UPDATE: Dodano dużo więcej kodu

Odpowiedz

6

W kodzie dana DraggableToolbarView instancja ma dwa właściwości łączą się z delegatów, jeden o nazwie toolbarViewDelegate której dziedziczy jej nadrzędnej, a jeden o nazwie draggableToolbarViewDelegate który jest zdefiniowany w DraggableToolbarView się. Musisz ustawić oba, jeśli chcesz, aby kontroler otrzymał wszystkie wiadomości delegatów.

Jednak to, co próbujesz zrobić, jest możliwe. Musisz użyć tej samej nazwy właściwości w obu klasach widoku, aby było tylko jedno połączenie delegata dla dowolnej instancji.

Najpierw zmień nazwę delegata w superklasie. (Zauważ, że nie trzeba, a nawet nie powinno niepokoić, aby zadeklarować ivar dla nieruchomości - to stworzony przez @synthesize.)

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

będzie użyć tej samej nazwy właściwości w podklasie.

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

Jest to dozwolone, o ile nazwa ivar podkładowej w podklasie jest inna niż w nadrzędnej, np

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

teraz zmienić wszystkie wiadomości delegata w dwóch klasach widoku do korzystania z tego jedną właściwość:

- (void)showBars 
{ 

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

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

teraz możesz wysłać setDelegate: do DraggableToolbarView i będzie korzystać z tego samego delegata dla metod przeciąganie i show/hi de metody.

Wreszcie, terminologia/nota wyjaśniająca. W odpowiedzi na your previous question, Caleb użył poprawnego terminu dla "ułożonych" protokołów, a Richard nie. Protokoły nie przechodzą od siebie po, ale jeden protokół może przyjąć drugi. Relacja jest podobna, ale odrębna. Kiedy obiekt jest zgodny z protokołem, obiecuje implementację metod zadeklarowanych w tym protokole. Brak implementacji przychodzi wraz z protokołem. To samo dotyczy jednego protokołu przyjmującego drugi - metody są zadeklarowane tylko w obu.Kiedy piszesz:

@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate> 

mówisz, że każdy przedmiot, który zapowiada wdrożenie metod DraggableToolbarViewDelegate „s będzie również wdrożenie metod z ToolbarViewDelegate. To wszystko, co to znaczy. Ponownie, żadna implementacja nie jest zgodna z tą obietnicą.

W tym przypadku oznacza to, że DraggableToolbarView może oczekiwać, że jego delegat wdroży metody w ToolbarViewDelegate.

+0

Doceń ten świetny post. Sądzę, że mogę trzymać się osobno, nie będąc wielkim fanem nazwy. Co zwykle robisz lub polecasz? –

+0

Cieszę się, że mogę pomóc. Nie widzę niczego złego w przesłonięciu własności delegata; sprawia, że ​​obie strony kodu są czystsze. –

1

Nie dały cały kod, ale z tego co jest tutaj, Upewnij się, że

  1. Twój ToolBarView i jej podklasy mają id <ToolBarViewDelegate> delegata jako własność.
  2. Twój DraggableToolbarViewDelegate rozszerza protokół NSObject.
  3. i Twój inny obiekt ViewController jest zgodny z protokołem delegowania, a nie z widokiem paska narzędzi.
  4. Gdy kontroler daje implementację metod delegatów i dostosowuje się do protokołu, ustaw obiekt delegata widoku na własny, a następnie użyj właściwości delegata ustawionej w widoku, aby wywołać te metody protokołów.