2009-08-17 13 views
16

Voy a escribir mi propio control personalizado que es muy diferente de UIButton. Es tan diferente que decidí escribirlo desde cero. Entonces, todo lo que subclase es UIControl.¿Cómo implementar el mecanismo de acción objetivo para el control personalizado?

Cuando mi control se retoca en el interior, entonces deseo disparar un mensaje en el medio de la acción del objetivo. El usuario de esa clase puede instanciarlo y luego agregar algunos objetivos y acciones para este evento.

es decir, imagino que llamaría internamente a un método -fireTargetsForTouchUpEvent. ¿Cómo podría mantener este mecanismo de acción objetivo en mi clase? ¿Tengo que agregar todos los objetivos y acciones a mi propia matriz y luego simplemente llamar selectores (las acciones) en los objetos de destino en un for-loop? ¿O hay una forma más inteligente de hacerlo?

Me imagino que proporcionar algunos métodos para agregar objetivos y acciones para algunos eventos como el evento de retoque (lo planteo manualmente llamando a un método interno cuando eso sucede). ¿Alguna idea?

+0

Por lo general, los controles tienen un objetivo, un selector por evento. ¿Quieres mas? –

+0

¿Podría tener más, si quisiera? Creo que sí...pero no estoy seguro –

Respuesta

5

Puesto que usted está pensando en una subclase uicontrol, sólo puede utilizar

- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents; 

uso de este, cualquier clase puede registrarse a sí mismo como objetivo para cualquier evento que desee en su controlador personalizado.

13

Tiene la idea correcta. Así es como yo lo haría:

@interface TargetActionPair : NSObject 
{ 
    id target; 
    SEL action; 
} 
@property (assign) id target; 
@property (assign) SEL action; 
+ (TargetActionPair *)pairWithTarget:(id)aTarget andAction:(SEL)selector; 
- (void)fire; 
@end 

@implementation TargetActionPair 
@synthesize target; 
@synthesize action; 

+ (TargetActionPair *)pairWithTarget:(id)aTarget andAction:(SEL)anAction 
{ 
    TargetActionPair * newSelf = [[self alloc] init]; 
    [newSelf setTarget:aTarget]; 
    [newSelf setAction:anAction]; 
    return [newSelf autorelease]; 
} 

- (void)fire 
{ 
    [target performSelector:action]; 
} 

@end 

Con esa clase en su lugar, el almacenamiento de sus pares de destino/de acción es bastante sencillo:

MyCustomControl.h:

#import "TargetActionPair.h" 

@interface MyCustomControl : UIControl 
{ 
    NSMutableArray * touchUpEventHandlers; 
} 

- (id)init; 
- (void)dealloc; 

- (void)addHandlerForTouchUp:(TargetActionPair *)handler; 

@end 

MyCustomControl .m:

#import "TargetActionPair.h" 

@implementation MyCustomControl 

- (id)init 
{ 
    if ((self = [super init]) == nil) { return nil; } 
    touchUpEventHandlers = [[NSMutableArray alloc] initWithCapacity:0]; 
    return self; 
} 

- (void)dealloc 
{ 
    [touchUpEventHandlers release]; 
} 

- (void)addHandlerForTouchUp:(TargetActionPair *)handler 
{ 
    [touchUpEventHandlers addObject:handler]; 
} 

- (void) fireTargetsForTouchUpEvent 
{ 
    [touchUpEventHandlers makeObjectsPerformSelector:@selector(fire)]; 
} 

@end 

Después de eso, preparar el control se llevaría a cabo de la siguiente manera:

[instanceOfMyControl addHandlerForTouchUp: 
     [TargetActionPair pairWithTarget:someController 
           andAction:@selector(touchUpEvent)]; 
+0

guau, la respuesta más grande que he tenido aquí;) gracias! Para mi caso, descubrí que UIControl parece ofrecerme ya lo que necesito. ¡Pero cuando hay eventos personalizados especiales que necesitan procesarse, su técnica es excelente! –

+0

En realidad, para eventos personalizados, es posible que desee utilizar los bits UIControlEventApplicationReserved (16 disponibles) y call - (void) sendActionsForControlEvents: (UIControlEvents) controlEvents; – Felixyz

+0

Lo que falta aquí es una forma de eliminar un objetivo/acción y tal vez un cheque duplicado. – pixelfreak

38

Solo quiero aclarar qué dijo @Felixyz porque al principio no estaba claro para mí.

Si está subclasificando UIControl, incluso si va a tener un evento personalizado, no tiene que hacer un seguimiento de sus propios objetivos/acciones. La funcionalidad ya está ahí, todo lo que tiene que hacer es llamar al código de abajo en la subclase para lanzar el evento:

[self sendActionsForControlEvents:UIControlEventValueChanged];

Luego, en la vista o vista controlador que crea instancias de su encargo UIControl, acaba de hacer

[customControl addTarget:self action:@selector(whatever) forControlEvents:UIControlEventValueChanged];

para evento personalizado, simplemente definir su propia enumeración (por ejemplo, UIControlEventValueChanged es igual a 1 << 12). Solo asegúrese de que esté dentro del rango permitido definido por UIControlEventApplicationReserved

+0

Eso era lo que necesitaba, gracias –

Cuestiones relacionadas