Способ заставить UIButton непрерывно срабатывать во время нажатия и удержания?

Вы знаете, как Марио просто продолжает бежать вправо, когда вы нажимаете и удерживаете правую кнопку на крестовине? Точно так же я хочу, чтобы мой UIButton непрерывно запускал свое действие в течение всего времени, пока он удерживается нажатым. Возможно ли это для UIButton? Если нет, возможно ли это сделать с помощью UIImageView, переопределив метод обработки касания определенным образом? На самом деле, прежде чем пытаться сделать это с помощью UIButton, у меня было несколько UIImageViews (устроенных для работы в качестве D-Pad), которые были проверены методами обработки касания, но все начало запутываться, поэтому я подумал, что это можно было бы сделать проще с UIButton и, следовательно, переключился. Кто-нибудь, кто знает, как получить распознавание непрерывного, неподвижного (не сдвинутого) касания вниз, поделитесь, пожалуйста.


person RexOnRoids    schedule 24.05.2009    source источник


Ответы (4)


Не используйте кнопку, используйте мультитач и NSTimer:

Создайте локальный объект NSTimer внутри вашего интерфейса, а затем используйте его для запуска/отмены таймера.

-(void)movePlayer:(id)sender {
   <Code to move player>
}

-(void)touchesBegan:(NSSet*)touches  withEvent:(UIEvent*)event {
    timer = [NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:@selector(movePlayer:) userInfo:nil repeats:YES];
}

-(void)touchesEnded:(NSSet*)touches  withEvent:(UIEvent*)event {
   if (timer != nil) 
      [timer invalidate];
      timer = nil;
}

-(void)touchesMoved:(NSSet*)touches  withEvent:(UIEvent*)event {
    if (timer != nil) {
       [timer invalidate];
       timer = nil;
    }
}

Таким образом, вы можете повторять событие с предопределенным интервалом, не полагаясь на кнопку, и получать требуемое поведение повторения. Обратите внимание на триггер touchesMoved — если они двигают пальцем, это отменяет таймер, и игрок перестает двигаться.

person Alex Taylor    schedule 24.05.2009
comment
У вас 2 тача началось, я считаю 2-й должен быть тач перешел. - person freespace; 24.05.2009
comment
Отлично, но не могли бы вы исправить повторяющиеся триггеры touchesBegan на ваши предполагаемые touchesMoved, чтобы никто не запутался. - person RexOnRoids; 24.05.2009

Вы также можете сделать то, что показано в предыдущем ответе, и по-прежнему использовать UIButton.

Просто запустите таймер на «Touch Down» и остановите его на «Touch Up Inside» или «Touch Up Outside».

Лично мне нравится использовать UIButtons, потому что они предлагают некоторые встроенные визуальные улучшения, которые вам не нужно кодировать самостоятельно.

person Brian Stormont    schedule 15.06.2009
comment
Просто для ясности: события Touch Up Inside и Touch Up Outside должны быть настроены на остановку таймера. - person gerry3; 24.11.2010
comment
На мой взгляд, лучший ответ, чем выбранный. Можно настроить через конструктор интерфейсов. Кроме того, работа с IBActions обычно приводит к более чистому и понятному коду, чем touchesBegan и frieds. - person txulu; 23.12.2013
comment
Не забудьте обработать UIControlEventTouchCancel, если вы пойдете по этому пути. (Хотя я определенно рекомендую подкласс UIButton, который инкапсулирует NSTimer. Контроллеры представления, как правило, слишком велики, поэтому все, что вы можете сделать, чтобы переместить код за пределы из контроллера представления, — это хорошо.) - person Andrey Tarantsov; 07.09.2014
comment
UIControlEventTouchCancel у меня не работает, если пользователь держит кнопку и проводит пальцем за пределы области кнопки. Вместо использования события TouchCancel лучше использовать (на мой взгляд) TouchDragExit. В заключение мы используем: - person Tzegenos; 26.11.2015

Для меня работает следующее:

  1. Создайте кнопку.
  2. Создайте 2 метода (перестаньте касаться и начните касаться) либо в контроллере представления, либо в подклассе.
  3. Добавьте 3 события управления. Touch Up Inside и Touch Drag Exit, оба из которых переходят к методу прекращения касания, а Touch Down — к методу начала касания.
  4. Когда вы начинаете касаться вызова метода, мы должны запустить NSTimer с интервалом примерно 0,2 (это зависит от вас, как быстро вы хотите, чтобы его вызывали), повторить true и в качестве селектора метод, который вы хотите вызвать (имея фактические вещи, которые вы хотите выполняться, когда пользователь нажимает кнопку).
  5. Когда вызывается метод остановки касания, мы должны аннулировать таймер (.invalidate()) и присвоить таймеру значение nil.

Это все!

person Tzegenos    schedule 26.11.2015

А теперь кое-что совершенно другое:
ReactiveCocoa 6.

self.button.reactive
    .controlEvents([.touchDown])
    .observeValues { button in
        SignalProducer.timer(interval: .milliseconds(500), on: QueueScheduler.main)
            .take(until: button.reactive.controlEvents([.touchDragOutside, .touchDragExit, .touchUpInside, .touchUpOutside, .touchCancel]).map { _ in return })
            .prefix(value: Date())
            .startWithValues { date in
                NSLog("\(date)")
            }
        }
person bteapot    schedule 02.08.2017