我已经提到了关于按下按钮的无数其他问题,但与Swift没有太多关联.我使用touchUpInside事件将一个功能连接到一个按钮:
@IBAction func singleFire(sender: AnyObject){ //code }
...和另一个功能,用于在按住相同按钮时重复调用上述功能,并在不再按下按钮时停止:
@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() } }
我不确定我做错了什么,我不知道如何将触摸事件设置为同一个按钮以实现不同的功能.
按住按钮时,您希望快速重复射击.
您buttonDown
和buttonUp
方法需要在顶层定义,而不是在另一个函数内定义.出于演示目的,@IBAction
从Storyboard中放弃连接更简洁,只需设置按钮viewDidLoad
:
class ViewController: UIViewController { @IBOutlet weak var button: UIButton! var timer: Timer? var speedAmmo = 20 @objc func buttonDown(_ sender: UIButton) { singleFire() timer = Timer.scheduledTimer(timeInterval: 0.3, target: self, selector: #selector(rapidFire), userInfo: nil, repeats: true) } @objc func buttonUp(_ sender: UIButton) { timer?.invalidate() } func singleFire() { print("bang!") } @objc func rapidFire() { if speedAmmo > 0 { speedAmmo -= 1 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: #selector(buttonDown), for: .touchDown) button.addTarget(self, action: #selector(buttonUp), for: [.touchUpInside, .touchUpOutside]) } }
另外,我改.touchUpOutside
到[.touchUpInside, .touchUpOutside]
(她俩润色事件),并呼吁singleFire
在初始buttonDown
的单火.通过这些更改,按下按钮会立即触发,然后0.3
只要按住按钮,就会每秒触发一次.
该按钮可以在故事板中连接,而不是在其中进行设置viewDidLoad
.在这种情况下,添加@IBAction
到buttonDown
和buttonUp
.然后Control-点击你的故事板左键并拖动,从旁边的圆圈向下触摸到func buttonDown
,并拖动从旁边的圆圈触摸的内心和润色外到func buttonUp
.
在我的原始答案中,我回答了如何让按钮同时识别水龙头和长按的问题.在澄清的问题中,只要用户按下手指,您就会希望此按钮持续"触发".如果是这种情况,则只需要一个手势识别器.
例如,在Interface Builder中,将长按手势识别器从对象库拖到按钮上,然后将"最小持续时间"设置为零:
然后你可以control从长按手势识别器中拖动到助手编辑器中的代码并添加一个@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") }
或者,如果您还想在用户将手指拖离按钮时停止触发,请添加对手势位置的检查:
@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 } }
我的原始答案,回答了如何识别按钮上的水龙头和长按的不同问题,如下所示:
就个人而言,我会使用点按和长按手势识别器,例如:
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
.它只取决于所需的用户体验.
仅供参考,您也可以在Interface Builder中添加这两个手势识别器(只需将对象库中的相应手势拖到按钮上,然后control从手势识别器拖动到@IBAction
功能),但更容易说明是什么以编程方式显示它.