UIPinchGestureRecognizer только для выщипывания

Я пытаюсь создать UIPinchGestureRecognizer, который не работает, если пользователь ущипнул (раздвигает пальцы). Я знаю, что есть действительно простой способ сделать это, просто взяв шкалу распознавателя в методе действия и, если она больше 1, установите флаг и проигнорируйте все будущие вызовы. Тем не менее, это не работает для меня, у меня есть другие распознаватели жестов, которые требуют, чтобы этот распознаватель пинча не работал, поэтому мне нужно, чтобы он неправильно работал, когда пользователь зажимает в неправильном направлении.

Я попытался создать подкласс UIPinchGestureRecognizer:

@implementation BHDetailPinchGestureRecogniser {
    CGFloat initialDistance;
}

#pragma mark - Object Lifecycle Methods

- (id)initWithTarget:(id)target action:(SEL)action {
    self = [super initWithTarget:target action:action];
    if (self) {
        initialDistance = NSNotFound;
    }
    return self;
}

#pragma mark - UIGestureRecogniser Methods

- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)recogniser {
    if ([recogniser isKindOfClass:[UIPinchGestureRecognizer class]]) {
        return [self.delegate gestureRecognizerShouldBegin:self];
    } else return false;
}

- (void)reset {
    [super reset];
    initialDistance = NSNotFound;
}

#pragma mark - Touch Handling Methods

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (touches.count >= 2) {
        if (self.state == UIGestureRecognizerStatePossible) {
            // Keep hold of the distance between the touches
            NSArray *bothTouches = [touches allObjects];
            CGPoint location1 = [(UITouch *)bothTouches[0] locationInView:self.view];
            CGPoint location2 = [(UITouch *)bothTouches[1] locationInView:self.view];
            initialDistance = [self distanceBetweenPoint:location1 andPoint:location2];
        }
    } else {
        // Fail if there is only one touch
        self.state = UIGestureRecognizerStateFailed;
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"Moved. (tc, %lu) (state, %i) (id, %f)", (unsigned long)touches.count, self.state, initialDistance);
    if (touches.count >= 2) {
        if (self.state == UIGestureRecognizerStatePossible) {
            if (initialDistance != NSNotFound) {
                // Get the new distance and see if is is larger or smaller than the original
                NSArray *bothTouches = [touches allObjects];
                CGPoint location1 = [(UITouch *)bothTouches[0] locationInView:self.view];
                CGPoint location2 = [(UITouch *)bothTouches[1] locationInView:self.view];
                NSLog(@"Checking distance between points.");
                if ([self distanceBetweenPoint:location1 andPoint:location2] < initialDistance - 3.f) {
                    NSLog(@"Began");
                    self.state = UIGestureRecognizerStateBegan;
                } else if ([self distanceBetweenPoint:location1 andPoint:location2] > initialDistance) {
                    NSLog(@"Failed");
                    self.state = UIGestureRecognizerStateFailed;
                }
            }
        } else {
            self.state = UIGestureRecognizerStateChanged;
        }
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.state == UIGestureRecognizerStatePossible) self.state = UIGestureRecognizerStateFailed;
    else [super touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    self.state = UIGestureRecognizerStateCancelled;
}

#pragma mark - Helper Methods

- (CGFloat)distanceBetweenPoint:(CGPoint)point1 andPoint:(CGPoint)point2 {
    return sqrtf(powf(point1.x - point2.x, 2) + powf(point1.y - point2.y, 2));
}

@end

Я понял, что это не так просто, нужно будет обрабатывать несколько касаний, иногда перемещаемые касания имеют только одно касание, поэтому нужно будет удерживать касания, одно касание может закончиться, а другое начнется, и это все еще нужно часть щепотки. Кажется, что я теряю встроенную функциональность распознавателя пинча, когда все, что я хочу сделать, это заставить его потерпеть неудачу, если пользователь укажет в неправильном направлении.

Есть ли более простой способ добиться такого поведения без полной переписывания UIPinchGestureRecognizer? Вероятно, стоит упомянуть, что я не имею никакого контроля над другими распознавателями, которые я хочу потерпеть неудачу (они глубоко в чашах PSPDFViewController (сторонней библиотеки)).

1 ответ

Решение

Как насчет использования распознавателя жестов delegate помогать?

Установите делегата со следующей реализацией gestureRecognizerShouldBegin

func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
    if let pinch = gestureRecognizer as? UIPinchGestureRecognizer {
        return pinch.scale < 1
    }
    return true
}
Другие вопросы по тегам