2009-02-11 10 views
9

Soy nuevo en Objective C y cacao. Simplemente no entiendo cómo enviar mensajes a la supervista de una UIView. No puedo hacer que funcione. Esto es lo que he intentado hasta ahora:Cómo mensaje supervista en Objective C

En mi MainView tengo un método resetDrawType llamado:

- (void) resetDrawType { 
    self.drawType = foo; 
} 

También en el MainView creo una vista secundaria y agregarlo a MainView:

mySubView *mySubView = [[mySubView alloc] initWithFrame:CGRectMake(foo, foo, foo, foo)]; 
[self addSubview:mySubView]; 
[mySubView release]; 

Luego, cuando la subvista finalice su dibujo, quiero enviar el mensaje resetDrawType a su superview, que es MainView.

yo probamos este

[(MainView*)[self superview] resetDrawType]; 

y

[(MainView*)self.superview resetDrawType]; 

... lo que no funcionó. Aprendí sobre protocolos informales, así que agregué este código a MainView.h

@interface NSObject (resetters) 
    - (void) resetDrawType; 
@end 

Pero aún nada. siguiente me enteré de esto selector y trató esto en la subvista:

if ([self.superview respondsToSelector:@selector(resetDrawType:)]) 
    [self.superview performSelector:@selector(resetDrawType) withObject:nil]; 

Es también no funcionaba. ¿Qué estoy haciendo mal? Gracias por tu ayuda.

Respuesta

6

Bueno en primer lugar en Objective-C que no hay necesidad de echar a una clase específica para enviar un mensaje. Por ejemplo, solo puedes hacer;

[self.superview resetDrawType]; 

Proporcionando la vista padre tiene la siguiente función;

- (void) resetDrawType { 

} 

Entonces esto debería funcionar correctamente. No hay necesidad de usar protocolos informales.

también sus pruebas de selección está mal porque no coincide con la definición de la función "resetDrawType". @selector (resetDrawType :) prueba una función llamada "resetDrawType" que toma el parámetro, que el tuyo no.

Esto es cómo se prueba para la función anterior;

if ([self.superview respondsToSelector:@selector(resetDrawType)]) 
    [self.superview performSelector:@selector(resetDrawType)]; 

(En lugar de performSelector también puede enviar el mensaje directamente).

+0

Gracias. Intenté simplemente enviar el mensaje directamente. Pero no se llama. ¿La supervista también debe ser la vista principal? – rainerkohlberger

+0

Esos dos términos son sinónimos en mi diccionario mental. La supervista es la vista que contiene su vista. ¿Qué esperas que signifique? – Chuck

11

Usted no debe tener un subvistas dicen su supervista mucho de nada. Debes hacer que la supervista sea un delegado de tu clase de vista.

// MainView 
MyView *myView = [[MyView alloc] initWithFrame:CGRectMake(...) delegate:self]; 

continuación, guarde el delegado a una variable de instancia declarada por id delegate.Cuando termine el dibujo:

// MyView 
- (void)doDrawing { 
    drawStuff(); 
    [delegate didFinishDrawingView:(MyView *)self] 
} 

Ahora, de vuelta en su MainView, poner en práctica este método

- (void)didFinishDrawingView:(MyView *)aView; 

a hacer lo que quiera.

El objetivo de todo esto es que las clases pequeñas al margen de su aplicación (como una pequeña subvista) no necesiten saber cómo funcionan las clases grandes que están encima de ellas. Esta configuración permite que la vista se comunique con la cadena, pero con un mensaje que transmite su propio estado en lugar de un mensaje que indica a otro objeto que haga algo específico. Esta es la forma en que Cocoa está estructurado para que las clases se puedan reutilizar fácilmente y sus eventos puedan ser reutilizados como lo necesite.

Su super visión debe saber qué hacer cuando finaliza su subvista. La subvista debería dejar que la gente sepa que está terminada.


Declarar una variable de instancia en la cabecera de la clase subvista así:

id delegate; 

Escribir un initiailizer para su clase subvista que tiene este aspecto:

- (id)initWithFrame:(CGRect)frame delegate:(id)aDelegate { 
    [super initWithFrame:frame]; 
    delegate = aDelegate; 
    return self; 
} 

Ahora usted tiene un inicializador que aceptará a un delegado, guardará ese delegado y le permitirá llamar a los métodos.

+0

Gracias! Lamentablemente, todavía no funciona. Para esto: MyView * myView = [[MyView alloc] initWithFrame: CGRectMake (...) delegado: self]; me aparece "warning: no '-initWithFrame: delegate:' method found" Tal vez no lo haya escuchado "¿Entonces guarde el delegado en una variable de instancia declarada por el delegado de id"? – rainerkohlberger

+0

Debe crear un nuevo método de inicializador para aceptar un delegado (o cualquier otra variable) en init. He actualizado mi respuesta con más detalles sobre eso. –

Cuestiones relacionadas