2012-05-26 1 views
5

zu implementieren Ich habe eine Klasse namens ToolbarView, die eine Unterklasse von UIView ist und im Grunde erstellt eine UIView, die eine UIToolbar verschwindet/wieder auftaucht. Ich habe auch eine Unterklasse von ToolbarView namens DraggableToolbarView ermöglicht es dem Benutzer, die Ansicht auf dem Bildschirm zu ziehen.Versuchen, Delegat Vererbung

Ich muss einen Delegaten für ToolbarView erstellen, so dass es ein anderes Objekt/eine andere Klasse benachrichtigen kann, wenn die Symbolleiste wieder angezeigt wird und verschwindet. Ich muss auch einen Delegaten für DraggableToolbarView erstellen, damit ich ein anderes Objekt/eine andere Klasse benachrichtigen kann, wenn die Ansicht gezogen wird. DraggableToolbarViews-Delegat muss auch ein anderes Objekt/eine andere Klasse benachrichtigen, wenn die Symbolleiste erneut angezeigt wird und verschwindet.

So entschied ich mich ToolbarViewDelegate zu implementieren und haben DraggableToolbarViewDelegate von ihm erben und haben ihre eigene Methode wie folgt vor:

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

... 

Wenn ich dies tun nur die DraggableToolbarDelegate Methoden reagieren. Aber wenn ich auch [drabbleToolbarView setToolbarViewDelegate:self] mache, funktioniert es. Ich habe versucht, jeden Delegierten getrennt ohne erben zu tun und es funktioniert gut, so glaube ich, dass das Problem in keinem anderen Teil des Codes ist.

Wer weiß warum? Ich dachte, indem ich die Protokolle erben ließ, würde ich nicht auch das ToolbarViewDelegate für ein DraggableToolbar-Objekt setzen müssen.

UPDATE: Hinzugefügt viel mehr Code

Antwort

6

in Ihrem Code eine gegebene DraggableToolbarView Instanz zwei Eigenschaften an den Delegierten verbinden hat, nannte man toolbarViewDelegate, die sie von ihrer Oberklasse erben, und eine draggableToolbarViewDelegate genannt, die in DraggableToolbarView selbst definiert ist. Sie müssen beide festlegen, wenn der Controller alle Delegiertenmeldungen erhalten soll.

Was Sie versuchen, ist jedoch möglich. Sie müssen denselben Property-Namen in Ihren View-Klassen verwenden, sodass nur eine Delegate-Verbindung für eine Instanz vorhanden ist.

Ändern Sie zuerst den Namen des Delegaten in der Oberklasse. (Beachten Sie, dass Sie nicht brauchen, und in der Tat sollte sich nicht die Mühe, eine Ivar für die Eigenschaft zu erklären - es von @synthesize erstellt wird.)

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

Sie das gleiche Eigenschaftsnamen in der Unterklasse verwenden.

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

Dies wird solange der Name des Trägers Ivar in der Unterklasse unterschiedlich ist erlaubt als die von der übergeordneten Klasse, zum Beispiel

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

nun alle Delegierten Nachrichten in den beiden Ansichtsklassen ändern diese eine Eigenschaft zu verwenden:

- (void)showBars 
{ 

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

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

Jetzt Sie setDelegate: zu einem DraggableToolbarView senden können, und es wird den gleichen Delegaten für die schleppen Methoden und die Show verwenden/hallo de Methoden.

Schließlich eine Terminologie/Erläuterung. Als Reaktion auf your previous question verwendete Caleb den korrekten Begriff für "gestapelte" Protokolle, und Richard nicht. Protokolle nicht erben voneinander, aber ein Protokoll übernehmen die andere. Die Beziehung ist ähnlich, aber deutlich. Wenn ein Objekt einem Protokoll entspricht, verspricht es, die in diesem Protokoll deklarierten Methoden zu implementieren. Keine Implementierung kommt mit dem Protokoll. Dasselbe gilt für ein Protokoll, das das andere übernimmt - die Methoden werden nur in beiden erklärt.Wenn Sie schreiben:

@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate> 

Sie sagen, dass jedes Objekt, das DraggableToolbarViewDelegate ‚s Methoden zu implementieren verspricht auch die Methoden von ToolbarViewDelegate implementieren. Das ist alles was es bedeutet. Wiederum kommt keine Implementierung mit diesem Versprechen.

In diesem Fall kann ein DraggableToolbarView seinen Delegaten erwarten, die Methoden in ToolbarViewDelegate zu implementieren.

+0

Schätzen Sie diesen tollen Beitrag. Ich denke, ich bleibe einfach bei der Trennung der Delegierten, nicht ein großer Fan der Namensgebung. Was würdest du normalerweise tun oder empfehlen? –

+0

Ich bin froh, dass ich helfen konnte. Ich sehe nichts falsch daran, die delegate-Eigenschaft zu überschreiben; Es macht beide Seiten des Codes sauberer. –

1

Sie haben nicht den gesamten Code gegeben, aber von was auch immer hier draußen ist, Vergewissern Sie sich, dass

  1. Ihre ToolBarView und ihre Unterklassen haben einen id <ToolBarViewDelegate> Delegierten als Ein Besitz.
  2. Ihr DraggableToolbarViewDelegate erweitert das NSObject-Protokoll.
  3. und Ihr anderes ViewController-Objekt entspricht dem Delegate-Protokoll und nicht der Symbolleistenansicht.
  4. Sobald Ihr Controller die Implementierung von Delegates-Methoden implementiert und dem Protokoll entspricht, legen Sie den Delegaten des Objekts der Ansicht auf self fest und verwenden Sie dann die in der View festgelegte Delegate-Eigenschaft, um diese Protokollmethoden aufzurufen.