Привет, Эван, спасибо за твой ответ. Идентификатор радара, который я обнаружил, - 9540729

ление: проблема, кажется, в зависимости от другого GestureRecognizer для сбоя. Смотрите комментарии и тестовый проект ниже этого вопроса!

В моем приложении для iPhone у меня есть несколько UIB-кнопок в качестве подпредставлений. Представление также имеет UITapGestureRecognizer, который прослушивает касания двумя пальцами.

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

Теперь у меня вопрос: как заставить мои кнопки игнорировать нажатия при распознавании жеста?

Изменить: это мой распознаватель жестов.

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapped:)];
[doubleTap setNumberOfTouchesRequired:2];
[doubleTap setNumberOfTapsRequired:1];
[doubleTap setCancelsTouchesInView:YES];
[doubleTap setDelaysTouchesBegan:YES];
[doubleTap setDelaysTouchesEnded:YES];
[self.view addGestureRecognizer:doubleTap];
[doubleTap release];
 Cornelius01 июн. 2011 г., 14:07
Я сделал тестовый проект для этого:dl.dropbox.com/u/3996208/iPhone/toucheventtest.zip
 Cornelius01 июн. 2011 г., 13:46
После того, как Deepak и gcamp заверили, что cancellsTouchesInView должны работать, я продолжил расследование и обнаружил корень этой проблемы: рядом с жестом в моем примере у меня также есть распознаватель жестов двумя пальцами и двумя касаниями. Распознаватель doubleTap сверху настроен так, чтобы требовать сбоя этого twoFingerDoubleTap. По какой-то причине это препятствует работе «cancellsTouchesInView». Кто-нибудь знает, почему это происходит?

Ответы на вопрос(4)

delaysTouchesBegan свойство. Установите этоYES.

альтернатива

Отключите взаимодействие с пользователем на кнопках и прикрепите распознаватель касаний одним пальцем, как указано выше. В обработчике касания проверьте, попадает ли касание в пределы кнопки. Если это в пределах кнопки, сделайте[theButton sendActionsForControlEvents:UIControlEventTouchUpInside];, Это вызовет событие подстройки по желанию, даже если взаимодействие с пользователем отключено.

 Cornelius31 мая 2011 г., 17:17
Убрал оба (хотя значения по умолчанию должны быть одинаковыми?), И это не помогло. Тем не менее распознаватель жестов срабатывает и вызывается действие touchUpInside (связанное с Interfacebuilder) ... Должно быть, там что-то действительно странное ...: / / Я добавил некоторые записи, сначала запускается распознаватель жестов, затем кнопки. Кажется, что cancellsTouchesInView (по умолчанию NO) игнорируется?
 Deepak Danduprolu31 мая 2011 г., 17:06
Удалить обаdelaysTouchesEnded а такжеcancelsTouchesInView и попробовать. Я сделал пример приложения, и оно работает.
 Cornelius31 мая 2011 г., 16:37
Я уже делаю это, но это не помогает. Надо было упомянуть об этом в оригинальном посте, извините.
 Cornelius31 мая 2011 г., 17:00
Жест распознан, но кнопки все же нажаты
 Deepak Danduprolu31 мая 2011 г., 16:50
Каково поведение, когда вы используете это?

который отвечает на ваш вопрос

- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer

По сути, вы требуете, чтобы распознаватель двух касаний завершился неудачей, прежде чем принять одно касание.

Так,

[singleTapRecognizer requireGestureRecognizerToFail:twoTapRecognizer];
 gcamp31 мая 2011 г., 16:40
Это не отменит обычные сенсорные события, но если вы удалитеaddTarget:action:forControlEvents: что вы уже сделали и поместили только цель / действие в распознаватель одного нажатия, который должен работать.
 Cornelius31 мая 2011 г., 16:36
Так что мне нужно было бы добавить один распознаватель жестов к каждой из моих кнопок (у меня их много)? Будет ли это переопределять нормальные сенсорные события?

я столкнулся с той же ошибкой. Если вы опубликуете свой радар #, я обманываю его в bugreporter.

Я написал следующий обходной путь. Я создаю подкласс UITapGestureRecognizer, затем использую подкласс для отслеживания касаний, которые вызвали действие жеста. Если мы получим те же штрихи в штрихах, закругленных на виде, мы перенаправим на штрихи Отменено. 'немедленная цель' необходима, потому что вызов touchesEnded в представлении происходит после прикосновения жеста закругленным, но до вызова действия жеста.

RPTapGestureRecognizer.h:

#import <UIKit/UIKit.h>
#import <UIKit/UIGestureRecognizerSubclass.h>

@interface RPTapGestureRecognizer : UITapGestureRecognizer

@property (nonatomic, retain) NSSet *lastTouches;

- (void)setImmediateTarget:(id)inTarget action:(SEL)inAction;

@end

RPTapGestureRecognizer.m:

#import "RPTapGestureRecognizer.h"

@interface RPTapGestureRecognizer ()
@property (nonatomic) SEL immediateAction;
@property (nonatomic, assign) id immediateTarget;
@end

@implementation RPTapGestureRecognizer

@synthesize lastTouches;
@synthesize immediateAction, immediateTarget;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    self.lastTouches = nil;

    [super touchesBegan:touches withEvent:event];
}

- (void)setImmediateTarget:(id)inTarget action:(SEL)inAction
{
    self.immediateTarget = inTarget;
    self.immediateAction = inAction;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UIGestureRecognizerState startingState, finalState;

    startingState = self.state;
    [super touchesEnded:touches withEvent:event];
    finalState = self.state;

    if (startingState != finalState &&
        finalState == UIGestureRecognizerStateEnded) {
        /* Must copy; the underlying NSCFSet will be modified by the superclass, removing the touches */
        self.lastTouches = [[touches copy] autorelease];

        if (self.immediateAction)
            [self.immediateTarget performSelector:self.immediateAction
                                       withObject:self];
    }
}

- (void)dealloc
{
    self.lastTouches = nil;
    self.immediateTarget = nil;

    [super dealloc];
}

@end

По мнению:

@synthesize lastTapGesture

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (self.lastTapGesture && [self.lastTapGesture.lastTouches isEqualToSet:touches]) {
        [self touchesCancelled:touches withEvent:event];
        self.lastTapGesture = nil;
        return;
    }
 /* touches ended implementation here */
}

 - (void)willHandleMouseTapGesture:(RPTapGestureRecognizer *)tapGesture
{
    /* Because one tap gesture is dependent upon another, the touchesEnded method is still going to be called, instead of touchesCanceled.
     * This is an Apple bug against all versions of iOS at least up to 5.0. It will be called in the run loop before tapGesture's action is called.
     *
     * See http://stackoverflow.com/questions/6188997/how-to-cancel-button-tap-if-uigesturerecognizer-fires/6211922#6211922 for details.
     */
    self.lastTapGesture = tapGesture;
}

- (void)configureGestures
{
    /* Two finger taps */
     RPTapGestureRecognizer *tapGestureOne;
     tapGestureOne = [[[RPTapGestureRecognizer alloc] initWithTarget:self 
                                                              action:@selector(handleMouseTapGesture:)] autorelease];
     tapGestureOne.numberOfTapsRequired = 1;
     tapGestureOne.numberOfTouchesRequired = 2;
     [tapGestureOne setImmediateTarget:self action:@selector(willHandleMouseTapGesture:)];
     [self addGestureRecognizer:tapGestureOne];
     [myGestures addObject:tapGestureOne];

     RPTapGestureRecognizer *tapGestureTwo;
     tapGestureTwo = [[[RPTapGestureRecognizer alloc] initWithTarget:self 
                                                              action:@selector(handleMouseTapGesture:)] autorelease];
     tapGestureTwo.numberOfTapsRequired = 2;
     tapGestureTwo.numberOfTouchesRequired = 2;
     [tapGestureTwo setImmediateTarget:self action:@selector(willHandleMouseTapGesture:)];
     [self addGestureRecognizer:tapGestureTwo];
}
 Cornelius11 июл. 2011 г., 12:01
Привет, Эван, спасибо за твой ответ. Идентификатор радара, который я обнаружил, - 9540729
Решение Вопроса

это ошибка. Я подал отчет об ошибке в Apple. Большое спасибо за ваши подсказки, Дипак и gcamp!

Сообщение об ошибке:

Сводка: при добавлении двух UITapGestureRecognizer в представление, в котором один требует отказа другого (requireGestureRecognizerToFail :), свойство CancelsTouchesInView первого средства распознавания жестов игнорируется.

Шаги для воспроизведения: 1. Создайте два UITapGestureRecognizer (r1 и r2). 2. Настройте r1 так, чтобы требовать двух касаний и одного касания, и отложить касания. Начало 3. Настройте r2, чтобы требовать двух касаний и двух касаний, и отложить касания. Начать 4. Настройте r1, чтобы требовать r2 не удастся [r1 requiredGestureRecognizerToFail: r2] 5. Добавьте r1 и r2 в представление 6. Поместите UIB-кнопку в представление 7. Коснитесь двумя пальцами вида, нужно нажать кнопку.

Ожидаемые результаты: r1 должен быть распознан, а нажатие кнопки должно быть отменено (по умолчанию для cancellsTouchesInView установлено значение YES для UITapGestureRecognizers).

Фактические результаты: r1 распознан, но также происходит событие кнопки touchedUpInside.

Регрессия: cancelTouchesInView отлично работает для r1, как только вы удалите зависимость от r2 (шаг 4).

Ваш ответ на вопрос