0

I'm having some trouble getting my UILongPressGestureRecognizer to only call itself once. I have a button that I longpress down for the duration of a recording and then upon release, it's supposed to stop the recording. For some reason when I hold down the button, it calls UIGestureRecognizerBegan, then UIGestureRecognizerEnded twice. Basically, there are two recordings. One on the longpress and then on the release, it ends, but calls it again thus creating two recordings. I have one button that has multiple protocols firing at the same time and I'm curious if this is a problem. I took a look at this link:

UILongPressGestureRecognizer gets called twice when pressing down

but I'm not getting the results I want.

The button also zooms when the longpressstate begins and it goes back to it's regular size when the longpressstate ends so I have some animation code below as well that's happening all at the same time.

ButtonView.m

- initWithFrame

    [self.recordButton addTarget:self action:@selector(longPress:) forControlEvents:(UIControlEventTouchDown)];
    [self addSubview:self.recordButton];

    self.longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
    self.longPressGesture.allowableMovement = 100.0;
    self.longPressGesture.numberOfTouchesRequired = 1;
    [self.recordButton addGestureRecognizer:self.longPressGesture];

}

- (void)longPress:(UILongPressGestureRecognizer *)gr {

    if ([self.delegate respondsToSelector:@selector(buttonView:didTryToZoom:)]) {
        [self.delegate buttonView:self didTryToZoom:self.recordButton];
    }
       if ([self.delegate respondsToSelector:@selector(buttonView:didTryToShake:)]) {
        [self.delegate buttonView:self didTryToShake:self.recordButton];
    }
    if ([self.delegate respondsToSelector:@selector(recordButtonPressedWithGesture:)]) {
        [self.delegate recordButtonPressedWithGesture:(UIGestureRecognizerStateBegan)];
    }

    if ([self.delegate respondsToSelector:@selector(recordButtonReleasedWithGesture:)]) {
        [self.delegate recordButtonReleasedWithGesture: (UIGestureRecognizerStateEnded)];
     }
}

In my view controller, I'm calling my delegates from my ButtonView class and adapting to the protocols by calling it in -viewDidLoad.

Here are my delegate methods that I'm calling from my ButtonView class:

ViewController.m

- (void)recordButtonReleasedWithGesture:(UIGestureRecognizerState)state {

    if (state == UIGestureRecognizerStateEnded) {
            [self audioRecorderDidFinishRecording:self.recorder successfully:YES];

            NSData *data = [NSData dataWithContentsOfURL:self.recorder.url];
            [data writeToFile:[NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"%@", [[AudioController sharedInstance] filePath]]] atomically:YES];
            [[RecordingController sharedInstance] addRecordingWithURL:[[AudioController sharedInstance] filePath]
                                                          andIDNumber:[[AudioController sharedInstance] randomIDNumber]
                                                       andDateCreated:[[AudioController sharedInstance] createdAtDate]
                                                         andFetchDate:[[AudioController sharedInstance] fetchDate]
                                                        andSimpleDate:[[AudioController sharedInstance] simpleDateString]
                                                         andGroupName:[[AudioController sharedInstance] groupName]];


            [[RecordingController sharedInstance] save];
     }
}

- (void)recordButtonPressedWithGesture:(UIGestureRecognizerState)state {
    if (state == UIGestureRecognizerStateBegan) {
            self.buttonView.playButton.enabled = NO;
            self.recorder.delegate = self;
            self.recorder = [[AudioController sharedInstance] recordAudioToDirectory];
    }
}

- (void)buttonView:(ButtonView *)view didTryToShake:(UIButton *)button {
    if (self.containerView.state == ButtonStateNone) {
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
        [animation setDuration:0.1];
        [animation setRepeatCount:3];
        [animation setAutoreverses:YES];
        [animation setFromValue:[NSValue valueWithCGPoint:
                             CGPointMake([self.buttonView.recordButton center].x + 20, [self.buttonView.recordButton center].y)]];
        [animation setToValue:[NSValue valueWithCGPoint:
                           CGPointMake([self.buttonView.recordButton center].x - 20, [self.buttonView.recordButton center].y)]];
        [[self.buttonView.recordButton layer] addAnimation:animation forKey:@"position"];
    }
}

- (void)buttonView:(ButtonView *)view didTryToZoom:(UIButton *)button {
    if (self.containerView.state == ENUMS) {
        if (view.longPressGesture.state == UIGestureRecognizerStateBegan) {
            [UIView animateWithDuration:.5f
                              delay:0
                            options:UIViewAnimationOptionCurveEaseIn
                         animations:^{
                             self.containerView.hidden = YES;
                             self.buttonView.recordButton.transform = CGAffineTransformScale(self.buttonView.recordButton.transform, 3, 3);
                             self.buttonView.recordButton.alpha = .7;
        } completion:nil];
         }
    if (view.longPressGesture.state == UIGestureRecognizerStateEnded) {
        [UIView animateWithDuration:.25
                              delay:0
                            options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseOut
                         animations:^{
                             self.buttonView.recordButton.transform = CGAffineTransformScale(CGAffineTransformIdentity, .7, .7);
                             self.buttonView.recordButton.alpha = 1;

        } completion:^(BOOL finished) {
                    [UIView animateWithDuration:.15
                                          delay:0
                                        options:UIViewAnimationOptionTransitionCrossDissolve
                                     animations:^{
                        self.buttonView.recordCompleteLabel.hidden = NO;
                        [NSTimer scheduledTimerWithTimeInterval:.65
                                                         target:self
                                                       selector:@selector(hideLabel)
                                                       userInfo:nil
                                                        repeats:NO];

                        self.buttonView.recordButton.transform = CGAffineTransformIdentity;

                    } completion:^(BOOL finished) {
                        self.containerView.hidden = NO;

                        //[self.containerView setState:ButtonStateNone];
                        [self noneState:ButtonStateNone];
                        self.buttonView.recordButton.backgroundColor = [UIColor blueColor];

I'm positive I'm missing something really silly and I'm just not seeing it. Are there any more seasoned developers that can identify why the long press is getting called twice? I'd greatly appreciate any help.

Community
  • 1
  • 1
jasonnoahchoi
  • 871
  • 5
  • 16
  • Is your initWithFrame method is the initWithFrame method of super class and you overrided it? – Suttikeat Witchayakul Apr 03 '15 at 06:14
  • Try to debug and check that initWithFrame is called only once. The gesture regcog. maybe added to the button for 2 times and cause to call longPress method twice. – Suttikeat Witchayakul Apr 03 '15 at 06:22
  • Wow! You're completely correct. It is getting called twice. That's so odd. Is this because I am setting the frame of the subclassed UIView in the viewDidLoad of the ViewController? – jasonnoahchoi Apr 03 '15 at 06:42
  • Did you place the view in the storyboard and you call initWithFrame again in your code? – Suttikeat Witchayakul Apr 03 '15 at 06:56
  • Ah I figured it out. I had set a property to my other view by initializing the ButtonView class. There are still a few kinks I need to tinker with but you have put me on the right track. Thanks Suttikeat! – jasonnoahchoi Apr 03 '15 at 07:41

1 Answers1

0

I found out that I had been calling it in another subclass of UIView. However, I still had a problem with it creating duplicate recordings. I dove a bit deeper and I realized that I had a singleton controller that was calling the AVAudioRecorder and I was also instantiating another instance of AVAudioRecorder by creating a property of AVAudioRecorder inside of the ViewController and setting it to the singleton controller's AVAudioRecorder. Many thanks to Suttikeat.

jasonnoahchoi
  • 871
  • 5
  • 16