按住“重复点火”button
我已经提到了关于一个按住button的无数其他问题,但与Swift没有太多关系。 我有一个使用touchUpInside事件连接到button的function:
@IBAction func singleFire(sender: AnyObject){ //code }
…和另一个function,意思是在按住同一个button的同时重复调用上述function,而在不再按下该button时停止:
@IBAction func speedFire(sender: AnyObject){ button.addTarget(self, action: "buttonDown:", forControlEvents: .TouchDown) button.addTarget(self, action: "buttonUp:", forControlEvents: .TouchUpOutside) func buttonDown(sender: AnyObject){ timer = NSTimer.scheduledTimerWithTimeInterval(0.3, target: self, selector: "singleFire", userInfo: nil, repeats: true) } func buttonUp(sender: AnyObject){ timer.invalidate() } }
我不知道我做错了什么,我不知道如何设置触摸事件到不同的function相同的button。
按住button时,您希望快速重复点火。
你的buttonDown
和buttonUp
方法需要在顶层定义,而不是在另一个函数内部。 出于演示的目的,放弃从故事板中@IBAction
并且只需在viewDidLoad
设置button@IBAction
清楚了:
class ViewController: UIViewController { @IBOutlet weak var button: UIButton! var timer: NSTimer! var speedAmmo = 100 func buttonDown(sender: AnyObject) { singleFire() timer = NSTimer.scheduledTimerWithTimeInterval(0.3, target: self, selector: "rapidFire", userInfo: nil, repeats: true) } func buttonUp(sender: AnyObject) { timer.invalidate() } func singleFire() { print("bang!") } func rapidFire() { if speedAmmo > 0 { speedAmmo-- print("bang!") } else { print("out of speed ammo, dude!") timer.invalidate() } } override func viewDidLoad() { super.viewDidLoad() // These could be added in the Storyboard instead if you mark // buttonDown and buttonUp with @IBAction button.addTarget(self, action: "buttonDown:", forControlEvents: .TouchDown) button.addTarget(self, action: "buttonUp:", forControlEvents: [.TouchUpInside, .TouchUpOutside]) } }
另外,我将.TouchUpOutside
更改为[.TouchUpInside, .TouchUpOutside]
(同时捕获触摸事件),并在初始buttonDown
上调用singleFire
进行单次触发。 随着这些改变,按下button立即触发,然后每0.3
秒触发一次,直到按下button。
该button可以在Storyboard中连线,而不是在viewDidLoad
中设置。 在这种情况下,将@IBAction
添加到buttonDown
和buttonUp
。 然后按住Control键,在Storyboard上点击button,然后从Touch Down旁边的圆圈拖动到func buttonDown
,然后从Touch Up Inside和Outside Up Outside旁边的圆圈拖动到func buttonUp
。
在我最初的回答中,我回答了如何让一个button同时识别水龙头和长按的问题。 在澄清的问题中,似乎只要用户按住手指,就希望此button能够持续“启动”。 如果是这种情况,则只需要一个手势识别器。
例如,在Interface Builder中,将一个长按手势识别器从对象库拖到button上,然后将“Min Duration”设置为零:
然后,您可以在助手编辑器中控制从长按手势识别器到您的代码,并添加@IBAction
来处理长按:
var timer: NSTimer? @IBAction func longPressHandler(gesture: UILongPressGestureRecognizer) { if gesture.state == .Began { timer = NSTimer.scheduledTimerWithTimeInterval(0.3, target: self, selector: "handleTimer:", userInfo: nil, repeats: true) } else if gesture.state == .Ended || gesture.state == .Cancelled { timer?.invalidate() timer = nil } } func handleTimer(timer: NSTimer) { NSLog("bang") }
或者,如果您还想在用户将手指从button上拉开时停止触发,请添加手势位置检查:
@IBAction func longPressHandler(gesture: UILongPressGestureRecognizer) { if gesture.state == .Began { timer = NSTimer.scheduledTimerWithTimeInterval(0.3, target: self, selector: "handleTimer:", userInfo: nil, repeats: true) } else if gesture.state == .Ended || gesture.state == .Cancelled || (gesture.state == .Changed && !CGRectContainsPoint(gesture.view!.bounds, gesture.locationInView(gesture.view))) { timer?.invalidate() timer = nil } }
我的原始答案,回答了如何识别button和按下button的不同问题如下:
就我个人而言,我会使用轻按和长按手势识别器,例如:
override func viewDidLoad() { super.viewDidLoad() let longPress = UILongPressGestureRecognizer(target: self, action: "handleLongPress:") button.addGestureRecognizer(longPress) let tap = UITapGestureRecognizer(target: self, action: "handleTap:") tap.requireGestureRecognizerToFail(longPress) button.addGestureRecognizer(tap) } func handleTap(gesture: UITapGestureRecognizer) { print("tap") } func handleLongPress(gesture: UILongPressGestureRecognizer) { if gesture.state == .Began { print("long press") } }
如果你想用长按手势,你也可以在.Ended
执行你的动作。 这只取决于所需的用户体验。
仅供参考,您也可以在界面生成器中添加这两个手势识别器(只需将各自的手势从对象库拖到button上,然后从手势识别器控制 -drag到@IBAction
函数),但是更容易通过程序展示来说明正在发生的事情。
我更新了@vacawama示例代码swift 3.谢谢。
@IBOutlet var button: UIButton! var timer: Timer! var speedAmmo = 100 @IBAction func buttonDown(sender: AnyObject) { singleFire() timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector:#selector(rapidFire), userInfo: nil, repeats: true) } @IBAction func buttonUp(sender: AnyObject) { timer.invalidate() } func singleFire() { if speedAmmo > 0 { speedAmmo -= 1 print("bang!") } else { print("out of speed ammo, dude!") timer.invalidate() } } func rapidFire() { if speedAmmo > 0 { speedAmmo -= 1 print("bang!") } else { print("out of speed ammo, dude!") timer.invalidate() } } override func viewDidLoad() { super.viewDidLoad() button.addTarget(self, action:#selector(buttonDown(sender:)), for: .touchDown) button.addTarget(self, action:#selector(buttonUp(sender:)), for: [.touchUpInside, .touchUpOutside]) }