Чи можете ви приєднати UIGestureRecognizer до кількох переглядів?


228
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTapTap:)];
[self.view1 addGestureRecognizer:tapGesture];
[self.view2 addGestureRecognizer:tapGesture];
[tapGesture release];

У наведеному вище коді view2розпізнаються лише крани . Якщо я коментую третій рядок, тоді кнопок view1буде розпізнано. Якщо я маю рацію і ви можете використовувати розпізнавальник жестів лише один раз, я не впевнений, що це помилка чи просто потрібна додаткова документація.

Відповіді:


334

A UIGestureRecognizerслід використовувати з одним представленням. Я погоджуюся, що документація плямиста. Що UIGestureRecognizerмає єдине viewвластивість, це дає йому:

вид

Подання, до якого вкладається розпізнавальник жестів. (лише для читання)

@ властивість (неатомічний, лише для читання) перегляд UIView *

Обговорення Ви додаєте (або додаєте) розпізнавальник жестів до об’єкта UIView за допомогою методу addGestureRecognizer:.


11
Оскільки додавання розпізнавача жестів до перегляду відбувається під час виконання (проти часу компіляції).
TomSwift

1
Я зрозумів це, але так само, як виявити, що ми говоримо, що ми не використовували змінну, XCode міг би сказати, виходячи з коду, що ми передали один і той же розпізнавач у кілька переглядів і могли попередити кодер.
Zoltán Matók

1
Попередження компілятора щодо кількох представлень даних про призначення одного і того ж UITapGestureRecognizer - це нісенітниця, тому що, можливо, ви хочете це зробити спеціально, наприклад, якщо ви хочете перенести розпізнавальник жестів дотику навколо з одного погляду на інший. Однак це нерозумне обмеження, що розпізнавальник жестів не може бути використаний у кількох переглядах.
Ерік ван дер Нойт

1
iOS 9 тепер застосовує єдиний перегляд за розпізнавачем жестів, я використовував метод побудови інтерфейсу нижче, але тепер я отримую таке повідомлення, коли намагаюся його використовувати (деякі деталі вирізані для стислості): ПОПЕРЕДЖЕННЯ: Розпізнавальник жестів (< UITapGestureRecognizer: .....>) був налаштований у дошку розкадрування / xib, яку слід додати до більш ніж одного представлення (-> <UIView:; frame = (0 44; 600 536); NSArray ...:>; layer = <CALayer: ... >>) в той час, це ніколи не було дозволено і тепер застосовується. Починаючи з iOS 9.0, він буде розміщений у першому вікні, в який він завантажений.
Джордж Браун

Якщо ви додаєте до перегляду вдруге, цей перегляд було додано до того, як цей розпізнавальник автоматично отримує неприєднаний UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didPressed:)]; [self.view1 addGestureRecognizer:tapRecognizer]; [self.view2 addGestureRecognizer:tapRecognizer];вихідний вигляд1 не має масив розпізнавачів жестів; view2 має масив розпізнавачів жестів
kokos8998

48

Я обійшов це за допомогою наведеного нижче.

for (UIButton *aButton in myButtons) {

            UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
            longPress.minimumPressDuration=1.0;
            [aButton addGestureRecognizer:longPress];
            [longPress release];

}

Тоді в моєму методі handleLongPress я просто встановлюю UIButton, рівний виду розпізнавача жестів і розгалужую те, що я роблю на основі цієї кнопки

- (void)handleLongPress:(UILongPressGestureRecognizer*)gesture {
    if ( gesture.state == UIGestureRecognizerStateEnded ) {
        UIButton *whichButton=(UIButton *)[gesture view];
        selectedButton=(UIButton *)[gesture view];
    ....
}

1
Чудова відповідь. Дякую за тонну. Це могло б бути прийнятою відповіддю, якби питання було "Як ви приєднаєте UIGestureRecognizer до кількох переглядів?"
D_D

7
Це (або щось дуже близьке до цього) не працювало для мене. Я додав кілька поглядів у розпізнавальник жестів дотику в Interface Builder і підключив розпізнавач до дії. Дія називалася в будь-який час, коли натискали доданий вигляд, але жест. Перегляд завжди був останнім доданим видом.
Aneil Mallavarapu

Це дійсно приємна відповідь, а також дуже корисна і погоджуюся з @MicRO +1
Діліп

2
Aneil, це тому, що ти не створив нових примірників розпізнавача жестів. У цій відповіді, що відбувається в циклі, є те, що створюються нові екземпляри розпізнавачів жестів, до кожного з яких додано лише один вид. Усі вони можуть вказувати на одного і того ж обробника, де ви потім перевіряєте подання, щоб побачити, який з них торкнувся.
Ерік ван дер Нойт

1
Чи може хтось ще підтвердити, що це більше не працює в поточній версії Obj-C / Swift?
Максі Мус

18

Для Swift 3 на випадок, коли хтось цього вимагає: Грунтуючись на відповіді Бхавіка Ратода вище.

 func setGestureRecognizer() -> UIPanGestureRecognizer {

        var panRecognizer = UIPanGestureRecognizer()

        panRecognizer = UIPanGestureRecognizer (target: self, action: #selector(pan(panGesture:)))
        panRecognizer.minimumNumberOfTouches = 1
        panRecognizer.maximumNumberOfTouches = 1
        return panRecognizer
    }

        ///set the recognize in multiple views
        view1.addGestureRecognizer(setGestureRecognizer())
        view2.addGestureRecognizer(setGestureRecognizer())

3
це в основному створює кілька жестів для двох поглядів, все одно одне правило: кожен жест має прикріплювати лише один погляд
Абдоельрман,

3
Ні, функція створює жест щоразу, коли її називають
Абдоелрман

2
назва функції невірна. логічна функція тут - функція отримання. тож його слід назвати: getGestureRecognizeтому що саме ця функція виконує
Девід Шек

Добре працюй для мене! І код чистіший, ніж створювати декілька змінних або ставити цілий код для створення всередині addGestureRecognizer
Codenator81

11

Ми можемо зробити щось подібне, це легко і просто

1) створити функцію, як показано нижче у контролері (ця функція поверне GestureRecognizer)

-(UITapGestureRecognizer*)setRecognizer{
     UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openProfile)];
     [gestureRecognizer setNumberOfTapsRequired:1];
     return gestureRecognizer;
}

2) тепер встановіть цей розпізнавач у кількох видах перегляду

[self.view1 addGestureRecognizer:[self setRecognizer]]; 
[self.view2 addGestureRecognizer:[self setRecognizer]];

Це не працює для мене, коли я замість перегляду використовую дві мітки.
Міхір Оза

3
@Mihir Oza, він не може працювати безпосередньо для UILabels. Через мітки немає сенсу для взаємодії з користувачем. Якщо ви хочете додати жести для UILabels, додайте цей єдиний рядок labelName..isUserInteractionEnabled = true у Swift. Потім додайте жести.
iOS

Людина вже пізно, я це вже виправив. Але дякую за пропозицію. Ваш коментар буде корисним для користувачів стеків. Вдячний!
Міхір Оза

1
Гадаю, рядок setNumberOfTapsRequired:1не потрібен
Naveed Abbas

9

Ні, ви не повинні прикріплювати розпізнавачі жестів до більш ніж одного перегляду.

У документації Apple є ця чітка інформація:

Розпізнавачі жестів прикріплені до перегляду

Кожен розпізнавач жестів асоціюється з одним представленням. Навпаки, представлення може мати декілька розпізнавачів жестів, оскільки один вид може відповідати на багато різних жестів. Щоб розпізнавач жестів розпізнавав дотики, які виникають у певному вікні, ви повинні приєднати розпізнавальник жестів до цього подання.

Посібник з обробки подій для iOS - Розпізнавальник жестів Бібліотека розробників Apple

Хоча як інші згадують, вони можуть працювати в деяких випадках, це явно проти документації і може змінитися в будь-якій майбутній версії iOS.

Що ви можете зробити, це додати окремі розпізнавачі жестів до поглядів, які ви хочете відстежувати, і вони можуть спільно діяти.


4

Добре, якщо хтось не хоче кодувати додавання подання жестами для декількох кнопок, як kwalker відповів вище, і хочуть зробити це через Interface Builder, це може вам допомогти.

1) Ви можете додати розпізнавальник жестів довгого натискання з бібліотеки об'єктів, як і інші об'єкти, такі як UIButtons та UILabels.

введіть тут опис зображення Спочатку те, що я в кінцевому підсумку використав, я взяв лише одне

2) Встановіть посилання на торгові точки UIButtonта влаштовані дії з власником файлу.

введіть тут опис зображення

Примітка: Якщо у вас кілька UIButton або будь-якого іншого об'єкта, вам знадобиться окремий розпізнавач жестів для кожного з них. Більш детально, будь ласка, зверніться до цього мого питання. Помилка тегу UIButton у розпізнавальнику тривалих жестів


Пов’язати кілька розпізнавачів UIView з розпізнавачем гостей за допомогою IB дуже просто. Питання стосувалося генерації коду.
ОлексійВМП

3

якщо у вас фіксований погляд, я пропоную вам зробити щось подібне

[self.view1 addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTapTap:)]];
[self.view2 addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTapTap:)]];

таким чином зменшиться кілька різних непотрібних змінних


3

Ви можете створити загальне розширення для перегляду, щоб легко додати розпізнавачі жестів. Це лише приклад, але це може виглядати приблизно так

extension UIView {

    func setGestureRecognizer<Gesture: UIGestureRecognizer>(of type: Gesture.Type, target: Any, actionSelector: Selector, swipeDirection: UISwipeGestureRecognizer.Direction? = nil, numOfTaps: Int = 1) {
    let getRecognizer = type.init(target: target, action: actionSelector)

    switch getRecognizer {
    case let swipeGesture as UISwipeGestureRecognizer:
        guard let direction = swipeDirection else { return }
        swipeGesture.direction = direction
        self.addGestureRecognizer(swipeGesture)
    case let tapGesture as UITapGestureRecognizer:
        tapGesture.numberOfTapsRequired = numOfTaps
        self.addGestureRecognizer(tapGesture)
    default:
        self.addGestureRecognizer(getRecognizer)
    }
  }

}

Щоб додати розпізнавальний пристрій 2, ви просто подзвоните:

let actionSelector = #selector(actionToExecute)
view.setGestureRecognizer(of: UITapGestureRecognizer.self, target: self, actionSelector: actionSelector, numOfTaps: 2)

Ви також можете легко додати розпізнавач пальців

view.setGestureRecognizer(of: UISwipeGestureRecognizer.self, target: self, actionSelector: actionSelector, swipeDirection: .down)

і так далі. Просто пам’ятайте, що ціль повинна бути пов'язана з селектором.


2

Заміна класу на ' <UIScrollViewDelegate>'

І використовувати цей метод у .m класі:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

Цей метод допоможе вам увімкнути кілька пальців на одному огляді.


2

Як щодо переписування (відтворення) свого GestureRecognize кожного разу, коли ви додаєте розпізнавальник жестів, що вказує на один і той же функція. У нижньому випадку це працює. Я використовую IBOutletCollection

Швидкий 2:

@IBOutlet var topicView: [UIView]!

override func viewDidLoad() {
        for view in self.topicView as [UIView] {
        view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "viewClicked:"))
    }
}

func viewClicked(recognizer: UITapGestureRecognizer) {
    print("tap")
}

-6

Ви можете зробити це за допомогою цього коду моїх поглядів, які є переглядами зображень у xib.

- (void)viewDidLoad
{
    firstIV.tag = 501;
    secondIV.tag = 502;
    thirdIV.tag = 503;
    forthIV.tag = 504;

    [self addTapGesturetoImageView: firstIV];
    [self addTapGesturetoImageView: secondIV];
    [self addTapGesturetoImageView: thirdIV];
    [self addTapGesturetoImageView: forthIV];
}

-(void)addTapGesturetoImageView:(UIImageView*)iv
{
    iv.userInteractionEnabled = YES;
    UITapGestureRecognizer * textfielBGIVTapGasture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(textfielBGIVTapped:)];
    textfielBGIVTapGasture.numberOfTapsRequired = 1;
    [iv addGestureRecognizer:textfielBGIVTapGasture];
}

- (void)textfielBGIVTapped:(UITapGestureRecognizer *)recognizer {
    int tag = recognizer.view.tag-500;
    switch (tag) {
        case 1:
        {
            //firstIV tapped;
            break;
        }
        case 2:
        {
            //secondIV tapped;
            break;
        }
        case 3:
        {
            //thirdIV tapped;
            break;
        }
        case 4:
        {
            //forthIV tapped;
            break;
        }
        default: {
            break;
        }
    }
}

1
Ви створюєте кілька розпізнавачів жестів; моє первісне запитання стосувалося повторного використання розпізнавача жестів, чого ви не можете зробити.
кубі

1
Який сенс додавати 500до тегів усіх ваших поглядів, а потім віднімати 500? Чому б просто не запустити теги на 1(або навіть 0) замість 501?
ma11hew28

@MattDiPasquale, Неважливо, чи хочете ви почати з 1його тільки що я скопіював цей код з мого додатка, куди я його даю 501. Але так, не давай 0bcoz, я десь читав, що його завжди вказують на перегляд батьків, тому це створить ускладнення. Повірте, я зіткнувся з цим.
Діліп

Основним текстом документації є "Перегляд встановлює чітке посилання на розпізнавальник жестів". що означає, що погляд належить жесту. Жест може мати лише один власник. Дивіться посилання
Phantom59
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.