UIGestureRecognizer срабатывает дважды?
Я установил UITapGestureRecognizer в viewDidLoad моего контроллера представления, но каким-то образом он дважды запускает метод выбора для одного нажатия.
UITapGestureRecognizer *g = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openInMapsApp:)] autorelease];
[self.mapView addGestureRecognizer:g];
Мой метод:
-(void)openInMapsApp:(UIGestureRecognizer*)g {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@""
message:@"This will open this location in the Maps application. Continue?"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK",nil];
[alertView show];
[alertView release];
}
Ответы
Ответ 1
распознаватели жестов посылают действие с различным состоянием жестов. Так что это не ошибка. Обход проблемы:
UITapGestureRecognizer *g = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openInMapsApp:)] autorelease];
[self.mapView addGestureRecognizer:g];
-(void)openInMapsApp:(UIGestureRecognizer*)g {
if(g.state != UIGestureRecognizerStateRecognized)
return;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@""
message:@"This will open this location in the Maps application. Continue?"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK",nil];
[alertView show];
[alertView release];
}
Ответ 2
У меня появился двойной UIAlertView
. Как показал Николас Ростов выше, это сработало для меня. Оба состояния UIGestureRecognizerStateEnded
и UIGestureRecognizerStateRecognized
создали новый alertView, когда в блоке использовался [alertView show]
. Когда // [alertView show] закомментирован, оба они все еще появились на консоли, но произошло только одно действие.
-(void) handleTapGesture:(UIGestureRecognizer*)sender{
if(sender.state != UIGestureRecognizerStateRecognized)
return;
Ответ 3
Я могу подтвердить то же самое. Я отправил отчет об ошибке в Apple с примером проекта, демонстрирующим проблему.
Временное обходное решение, которое я нашел, - это немедленно отключить UITapGestureRecognizer перед показом оповещения. Затем в методе (-ях) делегирования UIAlertView, который вы реализуете, снова включите. Это требует от вас как-то отслеживать GR, но это кажется самым элегантным решением для времени.
Используя пример кода выше:
-(void)openInMapsApp:(UIGestureRecognizer*)g {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@""
message:@"This will open this location in the Maps application. Continue?"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK",nil];
g.enabled = NO;
self.activeGestureRecognizer = g;
[alertView show];
[alertView release];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
self.activeGestureRecognizer.enabled = YES;
self.activeGestureRecognizer = nil;
}
- (void)alertViewCancel:(UIAlertView *)alertView {
self.activeGestureRecognizer.enabled = YES;
self.activeGestureRecognizer = nil;
}
Ответ 4
У меня была та же проблема, и я заметил, что второе событие имеет состояние UIGestureRecognizerStateCancelled (тогда как первым был UIGestureRecognizerStateEnded), поэтому другим обходным путем является игнорирование события в этом случае.
Ответ 5
Я только что решил аналогичную проблему. Оказалось, что у меня было добавлено два распознавателя жестов с помощью одного и того же вызова. То, как я узнал, - это NSLogging распознавателя жестов при вызове селектора.
На вашем месте я бы проверял, чтобы у вас не было двух распознавателей жестов: один из раскадровки, а другой - программно, например.
NSLog(@"recognizer: %@",[gestureRecognizer description]);
Ответ 6
Я добавил таймер в представление, которое проверяет, чтобы прикосновение было по крайней мере полсекунды назад и игнорировало второе касание, если оно слишком скоро.
Это только обходной путь. Я все равно хотел бы исправить настоящую проблему.
Ответ 7
if(g.state != UIGestureRecognizerStateBegan)
//instead of if(g.state != UIGestureRecognizerStateRecognized)
return;
Это вызовет предупреждение сразу после события жестов. например: если вы используете событие longtap, предупреждение будет отображаться после выключения вашего пальца. Но состояние UIGestureRecognizerStateBegan будет вызываться автоматически, если распознавание автоматически распознается.
Ответ 8
Я сделал это и работал:
сначала инициализируйте элемент на вашем объекте обработки, который хранит последний салфетки NSTimeInterval
-(id)initWithResourcePath:(NSString*)path {
if ([super init]) {
//some code
lastSwipe = 0;
}
return self;
}
Затем добавьте этот код в свой метод
-(void)viewDetectedRightSwipe:(UISwipeGestureRecognizer*)recognizer {
//touch being registered
NSTimeInterval thisTouch = [NSDate timeIntervalSinceReferenceDate];
//if the last swipe is the first swipe, then there nothing to do but the handling of a correct gesture
if(lastSwipe !=0) {
// find out how much time has passed between gestures
NSTimeInterval timeSinceLastTouch = thisTouch -lastSwipe ;
NSLog(@"thisTouch = %f",thisTouch);
NSLog(@"timeSinceLastTouch = %f",timeSinceLastTouch);
if (timeSinceLastTouch<0.2f) {
//return if this is an invalid touch
return;
} else {
// register the timestamp if it is valid
lastSwipe = thisTouch;
NSLog(@"left");
}
}
// invalid gestures won't be registed because they won't get to this portion of code.
lastSwipe = thisTouch;
NSLog(@"left");
// rest of the handling code
}