2015-05-14 12 views
11

Desidero creare una classe che possa ereditare da due classi personalizzate. Hai qualche idea per fare questo per favore? Si prega di vedere di seguito il mio esempio:Multi ereditarietà per IOS

di prima classe:

@interface UIZoomableView : UIView 
{ 
    UITapGestureRecognizer *_tapGestureRecognizer; 
} 

e realizzazione:

- (void)onDoubleTap:(UITapGestureRecognizer *)sender 
{ 
    CGSize newSize; 
    CGPoint centerPoint = self.center; 
    if ([self isSmall]) 
    { 
     newSize = [self bigSize]; 
    } 
    else 
    { 
     newSize = [self smallSize]; 
    } 

    [UIView animateWithDuration:0.3 animations:^{ 
     self.size = newSize; 
     self.center = centerPoint; 
    }]; 
} 

Seconda classe:

@interface UIDraggableView : UIView 

    UIPanGestureRecognizer *_panGestureRecognizer; 

@end 

implementazione:

- (void)handlePan:(UIPanGestureRecognizer*)sender 
{ 
    .. 
} 

Voglio creare una vista personalizzata che può essere zoomabile e trascinabile. Hai qualche idea per fare questo per favore? (senza copiare il codice ..)

Penso qualcosa di simile ai protocolli ma voglio il valore predefinito per le classi di base? Come posso implementare questo protocollo usando o protocolli simili.

Grazie per qualsiasi risposta!

+6

Objective-C non supporta l'ereditarietà multipla, si potrebbe trovare la soluzione migliore per essere protocolli. –

+0

Come posso implementarlo per favore? non voglio la proprietà che è delegata .. e voglio il valore di default per esempio nella vista ingrandibile voglio le piccole dimensioni predefinite, se la sottoclasse non sovrascrive la funzione, la classe restituisce (50,50). – Rebecca

+0

Non esiste un modo veramente valido per impostare valori predefiniti per un protocollo, in quanto dovrebbe essere non implementato. Quello che potresti fare è ereditare da una classe che implementa il protocollo, dai uno sguardo a questo aspetto: https://gist.github.com/paulrehkugler/9647085 –

risposta

4

Il più vicino a cui è possibile accedere all'eredità multipla nell'obiettivo C è con categorie. Questi sono un meccanismo per aggiungere metodi aggiuntivi a una classe che esiste già.

Si noti che questo ha alcune limitazioni importanti:

  1. Non è possibile aggiungere proprietà o Ivars utilizzando una categoria, anche se è possibile utilizzare associated objects per ottenere un effetto simile;
  2. Il compilatore non ti dirà se hai metodi con lo stesso nome che sono dichiarati nella classe e nella categoria, o in due categorie, quindi devi stare attento ad evitare la collisione del nome;
  3. Questo non verrà visualizzato come una classe appropriata (poiché l'Objective C non ha ereditarietà multiple), quindi non si avrà qualcosa nel codice chiamato ScrollableZoomableView che eredita da ScrollableView e ZoomableView. Questo non è possibile in Objective C (a differenza del C++ per esempio).
  4. È necessario il flag -ObjC quando si collegano i file con le categorie, altrimenti si verificheranno errori unrecognized selector quando si esegue il codice;
  5. Non è possibile richiamare il codice durante -init o +initialize, perché appartengono alla classe base. Avrai bisogno di inizializzare le tue proprietà in modo esplicito. Puoi comunque usare +load;
  6. Non è possibile intercettare neanche dealloc, quindi potrebbe essere necessario fare attenzione anche alla cancellazione esplicita degli ascoltatori.

volete qualcosa di simile:

@interface UIView (Zoomable) 

@property (nonatomic) UITapGestureRecognizer * my_tapGestureRecognizer; 

@end 


@implementation UIView (Zoomable) 

-(void)my_enableZooming() { 
    self.my_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(my_onDoubleTap:)]; 
    self.my_tapGestureRecognizer.numberOfTapsRequired = 2; 
    [self addGestureRecognizer:self.my_tapGestureRecognizer]; 
} 

-(void)my_disableZooming() { 
    [self removeGestureRecognizer:self.my_tapGestureRecognizer]; 
    self.my_tapGestureRecognizer = nil; 
} 

-(void)my_onDoubleTap:(UITapGestureRecognizer *)sender { 
    ... 
} 

-(UITapGestureRecognizer)my_tapGestureRecognizer { 
    return objc_getAssociatedObject(self, @selector(my_tapGestureRecognizer)); 
} 

-(void)setMy_tapGestureRecognizer:(UITapGestureRecognizer)value { 
    objc_setAssociatedObject(self, @selector(my_tapGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 

@end 


@interface UIView (Draggable) 

@property (nonatomic) UIPanGestureRecognizer * my_panGestureRecognizer; 

@end 

@implementation UIView (Draggable) 

-(void)my_enableDragging() { 
    self.my_panGestureRecognizer = ...; 
} 

-(void)my_disableDragging() { 
    ... 
} 

-(void)my_handlePan:(UIPanGestureRecognizer*)sender { 
    ... 
} 

-(UIPanGestureRecognizer)my_panGestureRecognizer { 
    return objc_getAssociatedObject(self, @selector(my_panGestureRecognizer)); 
} 

-(void)setMy_panGestureRecognizer:(UIPanGestureRecognizer)value { 
    objc_setAssociatedObject(self, @selector(my_panGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 

@end 
9

Objective-C non supporta l'ereditarietà multipla. È possibile utilizzare un protocollo, la composizione e l'inoltro dei messaggi per ottenere lo stesso risultato.

Un protocollo definisce un insieme di metodi che un oggetto deve implementare (è possibile avere anche metodi opzionali).La composizione è fondamentalmente la tecnica di includere un riferimento a un altro oggetto e chiamare quell'oggetto quando è richiesta la funzionalità. L'inoltro dei messaggi è un meccanismo che consente agli oggetti di trasferire messaggi su altri oggetti, ad esempio un oggetto incluso tramite la composizione.

di Apple Riferimento:

Quindi, nel tuo caso Composizione potrebbe essere una soluzione, sotto è il codice di esempio

@interface ClassA : NSObject { 
} 

-(void)methodA; 

@end 

@interface ClassB : NSObject { 
} 

-(void)methodB; 

@end 

@interface MyClass : NSObject { 
    ClassA *a; 
    ClassB *b; 
} 

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB; 

-(void)methodA; 
-(void)methodB; 

@end 

@implementation MyClass 

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB { 
    a = anA ; 
    b = aB ; 
} 

-(void)methodA { 
    [a methodA] ; 
} 

-(void)methodB { 
    [b methodB] ; 
} 

@end 

Se non si desidera implementare tutti i metodi da ClassA e ClassB in MyClass, è possibile utilizzare Inoltro di messaggi in MyClass per gestire tutte le chiamate di metodi. Qui di seguito funziona bene finché ClassA e ClassB non hanno metodi comuni.

@implementation MyClass 

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB { 
    a = anA ; 
    b = aB ; 
} 

//This method will be called, when MyClass can not handle the method itself 
-(void)forwardInvocation:(NSInvocation *)anInvocation 
{ 
    if ([a respondsToSelector:[anInvocation selector]]) 
     [a invokeWithTarget:someOtherObject]; 
    else if ([b respondsToSelector:[anInvocation selector]]) 
     [b invokeWithTarget:someOtherObject]; 
    else 
     [super forwardInvocation:anInvocation]; 
} 

@end 
2

Si potrebbe anche dare un'occhiata a questo articolo in objc.io sui comportamenti. È possibile creare comportamenti trascinabili e zoomabili e quindi aggiungerli a qualsiasi visualizzazione desiderata.

Here's the article.