LongPressGesture 与自定义代表被调用两次。是因为我的代表吗?
Posted
技术标签:
【中文标题】LongPressGesture 与自定义代表被调用两次。是因为我的代表吗?【英文标题】:LongPressGesture with custom delegates being called twice. Is it because of my delegates? 【发布时间】:2015-04-03 02:17:29 【问题描述】:我无法让我的 UILongPressGestureRecognizer 只调用一次自己。我有一个按钮,我在录制期间长按它,然后在释放时,它应该停止录制。出于某种原因,当我按住按钮时,它会调用 UIGestureRecognizerBegan,然后调用 UIGestureRecognizerEnded 两次。基本上,有两个录音。一个在长按上,然后在发布上,它结束,但再次调用它,从而创建了两个录音。我有一个按钮可以同时触发多个协议,我很好奇这是否是一个问题。我看了一下这个链接:
UILongPressGestureRecognizer gets called twice when pressing down
但我没有得到我想要的结果。
当长按状态开始时,按钮也会缩放,当长按状态结束时,它会恢复到正常大小,所以我在下面还有一些动画代码,这些都是同时发生的。
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)];
在我的视图控制器中,我从 ButtonView 类调用我的委托,并通过在 -viewDidLoad 中调用它来适应协议。
这是我从 ButtonView 类调用的委托方法:
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];
我很肯定我错过了一些非常愚蠢的东西,我只是没有看到它。是否有更多经验丰富的开发人员可以确定为什么长按会被调用两次?我将不胜感激任何帮助。
【问题讨论】:
你的initWithFrame方法是不是超类的initWithFrame方法被你覆盖了? 尝试调试并检查是否只调用了一次 initWithFrame。手势regcog。可能会添加到按钮 2 次并导致调用 longPress 方法两次。 哇!你完全正确。它被调用了两次。这太奇怪了。是不是因为我在 ViewController 的 viewDidLoad 中设置了子类 UIView 的框架? 您是否将视图放在情节提要中并在代码中再次调用 initWithFrame? 啊,我想通了。我通过初始化 ButtonView 类为我的另一个视图设置了一个属性。我还有一些问题需要修补,但你让我走上了正确的轨道。谢谢 Suttikeat! 【参考方案1】:我发现我一直在 UIView 的另一个子类中调用它。但是,我仍然在创建重复录音时遇到问题。我深入一点,我意识到我有一个调用 AVAudioRecorder 的单例控制器,并且我还通过在 ViewController 中创建 AVAudioRecorder 的属性并将其设置为单例控制器的 AVAudioRecorder 来实例化另一个 AVAudioRecorder 实例。非常感谢 Suttikeat。
【讨论】:
以上是关于LongPressGesture 与自定义代表被调用两次。是因为我的代表吗?的主要内容,如果未能解决你的问题,请参考以下文章
释放 LongPressGesture SwiftUI 时触发动作
如何取消 LongPressGesture 以便 PanGesture 可以识别
DragGesture 正在取消 SwiftUI 中的 LongPressGesture
SwiftUI - 当手指移动一点时让 LongPressGesture 保持不变?
在 UICollectionView 中使用 LongPressGesture 检索 UICollectionViewCell 的 NSIndexPath 和部分