问题
You know how Mario just keeps running to the right when you press and hold the right-button on the D-Pad? In the same manner, I want my UIButton to continuously fire its action for the duration that it is held down. Is this possible for a UIButton? If not, is this possible to do with a UIImageView by overriding a touch handling method in a certain way? Actually, before trying to do get this done with UIButton I had some UIImageViews (Arranged to function as a D-Pad) that were checked by touch handling methods but things started to get messy so I thought this could be done easier with UIButton and thus switched over. Anybody who knows how to get recognition of a continuous, stationary (not-moved) down-touch, please share.
回答1:
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.
回答2:
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.
回答3:
For me the following works:
- Create a button.
- Create 2 methods (stop touching and start touching) either in view controller or to a subclass.
- 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.
- 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).
- When stop touching method invokes we should invalidate timer
(
.invalidate()
) and assign timer as nil.
That's all!
回答4:
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)")
}
}
来源:https://stackoverflow.com/questions/903114/way-to-make-a-uibutton-continuously-fire-during-a-press-and-hold-situation