Way to make a UIButton continuously fire during a press-and-hold situation?

坚强是说给别人听的谎言 提交于 2019-11-27 03:01:46
Chaos

Don't use a button, use multi-touch and NSTimer:

Make a view-local NSTimer object inside your interface, then use it to start/cancel the timer

-(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;
    }
}

This way, you can repeat the event at a predefined interval, and not have to rely on a button, and get the repeat behaviour you're looking for. Note the touchesMoved trigger - if they move their finger, this cancels the timer, and the player stops moving.

You can also do similar to what is shown in the previous answer and still use a UIButton.

Just have the timer started on the "Touch Down" and have the timer stopped on either "Touch Up Inside" or "Touch Up Outside".

Personally, I like using UIButtons because they offer some built in visual enhancements you don't have to code on your own.

For me the following works:

  1. Create a button.
  2. Create 2 methods (stop touching and start touching) either in view controller or to a subclass.
  3. Add 3 Control Events. Touch Up Inside and Touch Drag Exit that both of them go to stop touching method and Touch Down goes with start touching method.
  4. When start touching method invokes we should start an NSTimer with interval approximately 0.2 (it's up to you how fast you would like to be invoked), repeat true and as a selector a method that you want to be invoked (having the actual stuff you want to execute when user hits the button).
  5. When stop touching method invokes we should invalidate timer (.invalidate()) and assign timer as nil.

That's all!

And Now for Something Completely Different:
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)")
            }
        }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!