Sous-class UIControl – Événements appelés deux fois

Je travaille actuellement sur une sousclass personnalisée UIControl. Pour suivre les touches, j'utilise la méthode suivante:

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { NSLog(@"Start"); CGPoint location = [touch locationInView:self]; if ([self touchIsInside:location] == YES) { //Touch Down [self sendActionsForControlEvents:UIControlEventTouchDown]; return YES; } else { return NO; } } 

Cela fonctionne comme prévu et @ "Start" est enregistré exactement une fois. L'étape suivante consiste à append une cible et un sélecteur avec UIControlEventTouchDown.

 [markItem addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside]; 

Cela fonctionne aussi et l'action: méthode est appelée. Mais c'est mon problème. L'action est appelée deux fois. Qu'est-ce que je fais mal? Je viens d'utiliser [self sendActionsForControlEvents:UIControlEventTouchDown]; une fois et l'action cible est appelée deux fois. Qu'est ce qui ne va pas avec mon code?

Sandro Meier

Le premier appel à la méthode d'action se produit automatiquement par le répartiteur d'events une fois que vous avez appelé:

 [markItem addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside]; 

save le gestionnaire.

Alors quand vous appelez alors:

 //Touch Down [self sendActionsForControlEvents:UIControlEventTouchDown]; 

vous générez le deuxième appel à votre gestionnaire (et tous les autres qui sont connectés).

Il semble donc que vous n'avez pas besoin à la fois du gestionnaire d'actions et de la fonction beginTracking – utilisez l'un ou l'autre.

Mettre à jour:

Compte tenu de votre commentaire et de votre reflection: étant donné que vous êtes une sous-class d'UIControl, je pense que vous ne voulez probablement pas vous inscrire à des gestionnaires d'events pour vous-même.

Au lieu de cela, vous devez utiliser exclusivement:

 - (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event; - (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event; - (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event; - (void)cancelTrackingWithEvent:(UIEvent *)event; // event may be nil if cancelled for non-event reasons, eg removed from window 

Aussi la variable d'instance de tracking .

Donc, je pense que vous ne devriez pas afficher des events ou écouter des events. De plus, est-il réellement possible d'get un événement beginTrackingWithTouch si ce n'est pas à votre avis? Ça ne semble pas être le cas. Donc, je ne pense pas que vous ayez besoin des tests pour voir si c'est à votre avis.

Je pense donc qu'il vaut la peine de prendre du recul et de réfléchir à ce que vous essayez de faire et de relire la documentation de UIControl. Plus précisément:

Notes de sous-classs Vous pouvez étendre une sous-class UIControl pour l'une des deux raisons suivantes:

Pour observer ou modifier l'envoi de messages d'action aux cibles pour des events particuliers Pour cela, remplacez sendAction:to:forEvent: évaluez le sélecteur transmis, l'object cible ou le masque de bits UIControlEvents et procédez comme requirejs.

Pour fournir un comportement de suivi personnalisé (par exemple, pour modifier l'apparence des surbrillances) Pour cela, remplacez une ou toutes les methods suivantes: beginTrackingWithTouch:withEvent: continueTrackingWithTouch:withEvent: endTrackingWithTouch:withEvent:

La première partie consiste à faire en UIControl votre sous-class UIControl non standard le traitement des actions cibles pour les clients ou les users de votre contrôle (cela ne ressemble pas à ce que vous essayez de faire, bien que vous n'ayez pas vraiment la description).

La deuxième partie ressemble plus à ce que vous voulez faire – suivi personnalisé dans votre sous-class UIControl .

Hm .. Vérifiez mon code pour vos objectives:

UIContr.h

 @interface UIContr : UIControl { } @end 

UIContr.m

 #import "UIContr.h" @implementation UIContr - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code. } return self; } - (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { NSLog(@"Start"); CGPoint location = [touch locationInView:self]; if (CGRectContainsPoint(self.frame, location)) { //Touch Down [self sendActionsForControlEvents:UIControlEventTouchDown]; return YES; } else { return NO; } } - (void)dealloc { [super dealloc]; } @end 

Comment utiliser dans UIViewController:

 - (void)viewDidLoad { UIContr *c = [[UIContr alloc] initWithFrame:CGRectMake(20, 20, 100, 100)]; [c addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside]; c.backgroundColor = [UIColor redColor]; [self.view addSubview:c]; } -(void)action:(id)sender{ NSLog(@"123"); }