2010-05-18 12 views
29

Quiero subclase UITextView, y enviar un nuevo mensaje al delegado. Entonces, quiero extender el protocolo de delegado. ¿Cuál es la forma correcta de hacer esto?cómo extender un protocolo para un delegado en el objetivo C, luego subclase un objeto para requerir un delegado conforme

Empecé con esto:

interfaz:

#import <Foundation/Foundation.h> 

@class MySubClass; 

@protocol MySubClassDelegate <UITextViewDelegate> 
- (void) MySubClassMessage: (MySubClass *) subclass; 
@end 


@interface MySubClass : UITextView { 
} 

@end 

aplicación:

#import "MySubClass.h" 


@implementation MySubClass 

- (void) SomeMethod; { 
    if ([self.delegate respondsToSelector: @selector (MySubClassMessage:)]) { 
     [self.delegate MySubClassMessage: self]; 
    } 
} 

@end 

sin embargo, con que me sale la advertencia: '-MySubClassMessage:' not found in protocol(s).

Tenía una forma de trabajar donde creé mi propio ivar para almacenar el delegado, luego también almacené el delegado usando [super setDelegate] pero me pareció incorrecto. tal vez no lo sea

Sé que puedo simplemente pasar la identificación y salir adelante, pero mi objetivo es asegurarme de que el compilador verifique que cualquier delegado que se suministre a MySubClass cumpla con el protocolo MySubClassDelegate.

Para más clairfy:

@interface MySubClassTester : NSObject { 

} 

@implementation MySubClassTester 

- (void) one { 
    MySubClass *subclass = [[MySubClass alloc] init]; 
    subclass.delegate = self; 
} 

@end 

producirá la advertencia: class 'MySubClassTester' does not implement the 'UITextViewDelegate' protocol

lo quiero para producir la advertencia sobre la no implementación del protocolo 'MySubClassDelegate' en su lugar.

+0

actualizado con más código de ejemplo para aclarar aún más, Brad me dejó más claro que el '' -MySubClassMessage: 'no encontrado en el protocolo' en realidad no indicaba que el compilador estaba comprobando que el delegado era de un tipo correcto . y ese @optional que tuve para MySubClassMessage hizo que la pregunta fuera casi discutible. ;) –

Respuesta

25

El UITextView define su delegate como

@property(nonatomic, assign) id<UITextViewDelegate> delegate 

lo que significa que se ajusta a UITextViewDelegate, y eso es lo compilador comprueba. Si desea utilizar el nuevo protocolo, es necesario redefinir delegate para cumplir con el protocolo:

@interface MySubClass : UITextView { 
} 
@property(nonatomic, assign) id<MySubClassDelegate> delegate 
@end 

El compilador no debe dar más advertencias.

[Actualización por faja]

... Con esto, el compilador le advertirá que los descriptores de acceso deben aplicarse ...[He implementado esto:]

-(void) setDelegate:(id<MySubClassDelegate>) delegate { 
[super setDelegate: delegate]; 
} 
- (id) delegate { 
return [super delegate]; 
} 

"

[Mi actualización]

creo que debería funcionar si sólo hacer una declaración @dynamic en lugar de reimplementar el método, ya que la aplicación es Ya está allí:

@dynamic delegate; 
+0

gracias. Con esto el compilador advertirá que los accessors necesitan ser implementados. a pesar de que están allí en la superclase. Anteriormente no pude implementar esto, y eso me llevó a almacenar el delegado en mi propio ivar. sin embargo, he intentado de nuevo darle una recomendación, y eso lo hizo. ¿Puedes agregar también tu respuesta para que tengan un buen formato: '- (void) setDelegate: (id ) delegate { [super setDelegate: delegate]; } - (id) delegado { return [super delegado]; } ' –

+0

@dynamic delegate. funciona. Muchas gracias, entiendo las cosas mucho mejor ahora. –

+2

¡Resulta que no necesita redefinir el delegado! Ver esta publicación: http: // stackoverflow.com/questions/732701/cómo-ampliar-protocolos-delegados-en-objetivo-c –

1

Dado que MySubClassMessage: es opcional, usted debe ser capaz de sencillo hacer un simple:

- (void) SomeMethod { 
    SEL delegateSelector = @selector(MySubClassMessage:); 
    if ([self.delegate respondsToSelector:delegateSelector]) { 
    [self.delegate performSelector:delegateSelector withObject:self]; 
    } 
} 

El compilador debe comprobar que la clase que implementa ajusta a su protocolo (o al menos dicen en la cabecera) y no obtendrá el error que describió.

+0

Dado que es opcional, ¿no se colgaría si el delegado no implementa el método? – Chuck

+0

@chuck, por sí mismo, sí. Por lo tanto, primero debe verificar que [self.delegate respondsToSelector: @selector (MySubClassMessage :)] se evalúe como verdadero. Editaré mi respuesta para tener el método completo –

+0

. Hay un buen punto. dado que mi ejemplo dice @optional realmente no importa si el objeto se está conformando. Estoy realmente interesado si no es opcional. Voy a sacar eso del ejemplo. Si entiendo esto correctamente, no es performSelector simplemente evitando la verificación de conformidad del protocolo aquí. ¿Todavía no sería posible asignar un delegado no conforme ya que los accesores de delegado están realmente definidos en la superclase UITextViews? –

7

Para cualquiera que esté interesado, esto puede hacerse simplemente así (para ke del ejemplo, yo subclase UIScrollView):

@protocol MySubclassProtocol <UIScrollViewDelegate> 
@required 
-(void)myProtocolMethod; 
@end 

@interface MySubClass : UIScrollView 

@property (nonatomic, weak) id <MySubclassProtocol> delegate; 

El detalle más importante aquí es la parte entre el <> después el nombre de su protocolo, que, dicho de una manera sencilla, las señales se están extendiendo ese protocolo. En su aplicación, todo lo que tiene que hacer entonces es:

@synthesize delegate; 

y ya está.

1

necesita extender los súper protocolo:

@protocol MYClassProtocol <SuperClassProtocol> 
-(void)foo; 
@end 

después de eso NO (!!!) crear la @property para el delegado de lo contrario se anula el objeto delegado original, sino simplemente reemplazar el método:

- (id<MYClassProtocol>)delegate 
{ 
    return (id<MYClassProtocol>)[super delegate]; 
} 

ahora puede utilizar el delegado de la manera clásica:

[self.delegate foo]; 
[self.delegate someSuperClassDelegateMethod]; 
Cuestiones relacionadas