Reputation: 573
I'd like to stop a button from being pressed for a certain amount of time after initially being pressed successfully.
My first thought is to user a timer and disable the button for a certain amount of time but I'm unsure how to implement this.
Could someone point me in the right direction please?
I'm using swift.
Upvotes: 7
Views: 6733
Reputation: 13726
#Swift 3.0# I think this extension is convenience:
extension UIControl {
func preventRepeatedPresses(inNext seconds: Double = 1) {
self.isUserInteractionEnabled = false
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + seconds) {
self.isUserInteractionEnabled = true
}
}
}
###How to use:###
@IBAction func pressedButton(_ sender: UIButton) {
sender.preventRepeatedPresses()
// do the job
}
Upvotes: 11
Reputation: 535566
No timer needed. No disabling needed.
When the button is tapped, store the current Date in an instance property. When the button is tapped again, just before you store the current Date in that same instance property, subtract the old Date from the new Date. If they are too close together, do not also perform the button's action, whatever it is.
In other words, you take action only if the two timestamps are sufficiently far apart.
This is called debouncing, and is a common technique. Do a search and you will find much discussion of it here.
EDIT: No Date storage needed, nowadays! Just use the Combine framework's built-in debounce
operator.
Upvotes: 14
Reputation: 51
If you want this to apply to all buttons in your app, you can extend UIButton as such:
extension UIButton {
override open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
self.isUserInteractionEnabled = false
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.isUserInteractionEnabled = true
}
}
}
If you have buttons that you do want to be able to hammer repeatedly, you could either use a specific extension class for those particular buttons, or create a custom extension class for all buttons with an @IBInspectable
of type Bool
to set whether or not a specific button should deactivate temporarily after being pressed.
Upvotes: 0
Reputation: 14904
You dont need a timer, could wait a few seconds and activate the button again.
So:
var ButtonIsActiv = false
func buttonPressed(button: UIButton) {
if ButtonIsActiv == false {
// do something with your button
ButtonIsActiv = true
// after 3 seconds, activate it again
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3)) {
ButtonIsActiv = false
}
} else {
// your button is not activated
}
}
Upvotes: 4
Reputation: 2455
How about this?
//
// ViewController.swift
// SwiftButtonStopStackOverflow
//
// Created by Seoksoon Jang on 29/09/2016.
// Copyright © 2016 Seoksoon Jang. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet var testButton: UIButton!
@IBAction func clickAction(_ sender: AnyObject) {
self.testButton.isEnabled = !self.testButton.isEnabled
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.testButton.isEnabled = !self.testButton.isEnabled
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Upvotes: 1
Reputation: 562
You could have a Bool in your controller that says if the button is actionable or not, and when the button is pressed, set the Bool, and schedule a TimeInterval, like so:
Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(<YourMethod>), userInfo: nil, repeats: false)
Another strategy would be after the button is pressed, disable the interaction with the property userInteractionEnabled
and then with the Timer, enable the property again.
Upvotes: 0