title: Tap gesture causes strange behavior
body: <p>I’m building a reaction test that requires the user to tap on the target dot, while other non-target dots come down.  It works most of the time but sometimes after tapping on a target dot it will display several other dots with weird behavior.  I’ve been looking at the code for days and I can’t find the problem.  Does anyone have any suggestions?
  Thanks much.  Here’s the code.</p>
  
  <pre><code>- (void)viewDidAppear:(BOOL)animated
  {
      [super viewDidAppear:animated];
  
      // single tap gesture recognizer
      self.myTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(theTap:)];
      self.myTap.numberOfTapsRequired = 1;
      [self.firstView addGestureRecognizer:self.myTap];
  
      self.myTap.enabled = NO;
  
      self.colorToHit = self.colorFromPreviousController;
  
      [self KickOff];
  }
  
  - (void)viewDidLoad
  {
      [super viewDidLoad];
  
      self.holdTheReactionTimes = [[NSMutableArray alloc] initWithCapacity:50];
      self.firstTime = YES;
      numberOfTries = 0;
  
  }
  
  #pragma mark - Utility Methods
  - (void)setRandomLocationForView:(UIView *)view
  {
  
      CGRect sinkBounds = CGRectInset(self.firstView.bounds, view.frame.size.width/2, view.frame.size.height/2);
  
      CGFloat x = arc4random() % (int)sinkBounds.size.width + view.frame.size.width/2;
      CGFloat y = arc4random() % (int)sinkBounds.size.height + view.frame.size.height/2;
  
      view.center = CGPointMake(x, y);
  }
  
  - (void)addLabel
  {
      [self stopDraining];
  
      static NSArray *buttons = nil;
  
      buttons = [[NSArray alloc] initWithObjects:
                 @"XX.png",
                 @"YY.png",
                 @"ZZ.png",
                 nil];
  
      int theIndex = arc4random()%[buttons count]; 
      NSLog(@"the index: %d", theIndex);
      NSString *theImageName = [buttons objectAtIndex:theIndex];
      CGRect anotherFrame = CGRectMake(10, 10, 64, 64);
      UIView *anotherView = [[UIView alloc] initWithFrame:anotherFrame]
      UIImageView  *imageView1 = [[UIImageView alloc] initWithFrame:CGRectMake(-2, -2, 64, 64)];
      imageView1.image = [UIImage imageNamed:theImageName];
      [anotherView addSubview:imageView1];
  
      [self setRandomLocationForView:anotherView];
      [self.firstView addSubview:anotherView];
  
      NSDate *date = [NSDate date];
      timeOne = [date timeIntervalSince1970];    
      if (theIndex == self.colorToHit) {
          NSLog(@"the right color");
          self.isThisTheRightColor = YES;
          self.myTap.enabled = YES;
          numberOfTries += 1;
  
      } else {
          NSLog(@"the wrong color");
          self.isThisTheRightColor = NO;
          self.myTap.enabled = NO;
          [self startDraining];
      }
  }
  
  #pragma mark - View Animation
  #define ANIMATE_DURATION 6.0
  #define SLEEP_INTERVAL 0.5
  
  - (void)theTap:(UITapGestureRecognizer *)gesture
  {
      NSLog(@"Tapped");
  
      float tapInterval = 0;
      CGPoint tapLocation = [gesture locationInView:self.firstView];
      for (UIView *view in self.firstView.subviews) {
          if (CGRectContainsPoint(view.frame, tapLocation)) {
              NSLog(@"we hit one");
              AudioServicesPlayAlertSound(kSystemSoundID_Vibrate); // added this 4-27
  
              if (self.firstTime) {
                  NSDate *date = [NSDate date];
                  timeTwo = [date timeIntervalSince1970];
                  NSLog(@"TAP First time: %f", timeTwo);
                  self.firstTime = NO;
              } else {
  
                  NSDate *date = [NSDate date];
                  timeTwo = [date timeIntervalSince1970];
                  NSLog(@"Second time: %f", timeTwo);
              }
  
              tapInterval = (timeTwo - timeOne);
              NSLog(@"Time Interval: %f", tapInterval);
  
              [view removeFromSuperview];
  
              [self writeTimeStampToArray:tapInterval];
          }
      }
  }
  
  - (void)KickOff
  {
      for (UIView *view in self.firstView.subviews) {
          [view removeFromSuperview];
      }
  
      if (self.firstView.window) {
          [self addLabel];
      }    
  }
  
  - (void)writeTimeStampToArray:(float)timeStamp
  {
      NSNumber *timeObject = [NSNumber numberWithFloat: timeStamp];
      [self.holdTheReactionTimes addObject:timeObject];
  
      if (numberOfTries &lt; NUMBER_OF_TRIES) {
          [self addLabel];
      } else {
          [self nextScreen];
      }
  }
  
  - (void)nextScreen
  {
      [self performSegueWithIdentifier: @"viewsummary" sender: self];
  }
  
      }
  }
  
  #pragma mark - Flipside View
  
  - (void)ReactionViewControllerDidFinish:(int)trynumber
  {
      self.tryNumberInt = trynumber;
      [self dismissViewControllerAnimated:YES completion:nil];
  
  }
  
  #define COUNTER 4
  
  //////////////
  // drain logic
  
  - (void)drain:(NSTimer *)timer
  {
      [self drain];
  }
  
  #define DRAIN_DURATION 2.0
  
  - (void)startDraining
  {
      self.drainTimer = [NSTimer scheduledTimerWithTimeInterval:DRAIN_DURATION/3
                                                         target:self
                                                       selector:@selector(drain:)
                                                       userInfo:nil
                                                        repeats:YES]; 
  }
  
  - (void)stopDraining
  {
      [self.drainTimer invalidate];
  }
  
  - (void)drain
  {
      for (UIView *view in self.firstView.subviews) {
          CGAffineTransform transform = view.transform;
          if (CGAffineTransformIsIdentity(transform)) {
              UIViewAnimationOptions options = UIViewAnimationOptionCurveLinear;
              [UIView animateWithDuration:DRAIN_DURATION/3 delay:0 options:options animations:^{
                  view.transform = CGAffineTransformRotate(CGAffineTransformScale(transform, 0.7, 0.7), 2*M_PI/3);
              } completion:^(BOOL finished) {
                  if (finished) {
                      [UIView animateWithDuration:DRAIN_DURATION/3 delay:0 options:options animations:^{
                          view.transform = CGAffineTransformRotate(CGAffineTransformScale(transform, 0.4, 0.4), -2*M_PI/3);
                      } completion:^(BOOL finished) {
                          if (finished) {
                              [UIView animateWithDuration:DRAIN_DURATION/3 delay:0 options:options animations:^{
                                  view.transform = CGAffineTransformScale(transform, 0.1, 0.1);
                              } completion:^(BOOL finished) {
                                  if (finished) [view removeFromSuperview];
                              }];
                          }
                      }];
                  }
              }];
          }
      }
  
      [self addLabel];
  
  }
  </code></pre>