2012-05-26 15 views
5

Ho una classe chiamata ToolbarView che è una sottoclasse di UIView e fondamentalmente crea un UIView che ha una UIToolbar che scompare/riappare. Ho anche una sottoclasse di ToolbarView chiamata DraggableToolbarView che consente all'utente di trascinare la vista sullo schermo.Provare a implementare l'ereditarietà dei delegati

Devo creare un delegato per ToolbarView in modo che possa notificare un altro oggetto/classe quando la barra degli strumenti riappare e scompare. Devo anche creare un delegato per DraggableToolbarView in modo da poter notificare un altro oggetto/classe quando la vista viene trascinata. Il delegato DraggableToolbarViews dovrà anche notificare un altro oggetto/classe quando la barra degli strumenti riappare e scompare.

così ho deciso di implementare ToolbarViewDelegate, e hanno DraggableToolbarViewDelegate ereditare da essa e avere un proprio metodo come segue:

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

... 

Quando faccio questo solo i metodi DraggableToolbarDelegate rispondono. Tuttavia quando faccio anche [drabbleToolbarView setToolbarViewDelegate:self] funziona. Ho provato a fare ogni delegato separatamente senza ereditarietà e funziona bene quindi credo che il problema non sia in nessuna altra parte del codice.

Chiunque potrebbe sapere perché? Ho capito facendo ereditare i protocolli, non avrei nemmeno dovuto impostare ToolbarViewDelegate per un oggetto DraggableToolbar.

UPDATE: Aggiunta molto più codice

risposta

6

Nel codice, qualsiasi DraggableToolbarView istanza ha due oggetti da collegare ai delegati, uno chiamato toolbarViewDelegate quale eredita dalla propria superclasse, e uno chiamato draggableToolbarViewDelegate che è definito nella DraggableToolbarView sé. Devi impostare entrambi se vuoi che il controller ottenga tutti i messaggi delegati.

Quello che stai cercando di fare è comunque possibile. È necessario utilizzare lo stesso nome di proprietà in entrambe le classi di visualizzazione, in modo che sia presente una sola connessione delegata per qualsiasi istanza.

Innanzitutto, modificare il nome del delegato nella superclasse. (Si noti che non è necessario, e in effetti non dovrebbe preoccuparsi, a dichiarare un Ivar per la proprietà - è creato da @synthesize.)

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

Si utilizzerà lo stesso nome di proprietà nella sottoclasse.

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

Ciò è consentito a condizione che il nome del Ivar supporto nella sottoclasse è diverso da quello della superclasse, ad esempio,

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

Ora cambiare tutti i messaggi delegato nelle due classi di visualizzazione per utilizzare questa una proprietà:

- (void)showBars 
{ 

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

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

Ora è possibile inviare ad un setDelegate:DraggableToolbarView e utilizzerà lo stesso delegato per i metodi di trascinamento e lo spettacolo/hi de metodi.

Infine, una terminologia/nota esplicativa. In risposta a your previous question, Caleb usava il termine corretto per i protocolli "impilati" e Richard no. I protocolli non ereditano l'uno dall'altro, ma un protocollo può adottare l'altro. La relazione è simile, ma distinta. Quando un oggetto è conforme a a un protocollo, promette di implementare i metodi dichiarati in tale protocollo. Nessuna implementazione arriva con il protocollo. Lo stesso vale per un protocollo che adotta l'altro - i metodi sono appena dichiarati esistere in entrambi.Quando si scrive:

@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate> 

lei sta dicendo che qualsiasi oggetto che promette di implementare metodi s' DraggableToolbarViewDelegate anche implementare i metodi da ToolbarViewDelegate. Questo è tutto ciò che significa. Ancora una volta, nessuna implementazione arriva con quella promessa.

In questo caso, ciò significa che un DraggableToolbarView può aspettarsi che il suo delegato applichi i metodi in ToolbarViewDelegate.

+0

Apprezzo quel bel post. Penso che potrei limitarmi a tenere separati i delegati, non un grande fan della cosa di nominare. Cosa faresti normalmente o raccomanderei di fare? –

+0

Contento di aver potuto aiutare. Non vedo nulla di sbagliato nel sovrascrivere la proprietà delegata; rende entrambi i lati del codice più pulito. –

1

Non hanno dato l'intero codice, ma da tutto ciò che è qui, Assicurarsi che

  1. tuo ToolBarView e le sue sottoclassi hanno un id <ToolBarViewDelegate> delegato come una proprietà.
  2. Il DraggableToolbarViewDelegate estende il protocollo NSObject.
  3. e l'altro oggetto ViewController è conforme al protocollo delegato e non alla vista barra degli strumenti.
  4. Una volta che il controllore dà attuazione ai metodi dei delegati e si conforma al protocollo, impostare il delegato dell'oggetto della vista su se stesso e quindi utilizzare la serie di proprietà delegate nella vista per chiamare questi metodi di protocollo.
Problemi correlati