Search code examples
iosiphoneswiftuibuttonuitapgesturerecognizer

UIButton that accepts 1 finger and 2 finger tap events


I'm keeping track of a game score, where the game points increment/decrement by 25.

I'm using UIButtons to show the score in the button label, take a tap gesture of 1 finger to increment the score by 25, and take a tap gesture of 2 fingers to decrement the score by 25.

I can't find a more modular way to write this code, the only function that is reusable for each button is:

func setButtonTitleAndIncrement(index: Int, button: UIButton) -> Int {
    var index = index
    index += 25
    button.setTitle(String(index), for: .normal)
    return index
}

func setButtonTitleAndDecrement(index: Int, button: UIButton) -> Int {
    var index = index
    index -= 25
    button.setTitle(String(index), for: .normal)
    return index
}

But for each button, I have to use this same code except specify specific buttons and methods, but I can't figure out a way around this. I'd love to take a general index and button at least. Any ideas?

var index1 = 0
var index2 = 0

override func viewDidLoad() {
    super.viewDidLoad()
    let oneFingerTapButtonTeam1 = UITapGestureRecognizer(target: self, action: #selector(incrementScoreTeam1))
    oneFingerTapButtonTeam1.numberOfTouchesRequired = 1
    buttonTeam1.addGestureRecognizer(oneFingerTapButtonTeam1)

    let twoFingerTapButtonTeam1 = UITapGestureRecognizer(target: self, action: #selector(decrementScoreTeam1))
    twoFingerTapButtonTeam1.numberOfTouchesRequired = 2
    buttonTeam1.addGestureRecognizer(twoFingerTapButtonTeam1)

    let oneFingerTapButtonTeam2 = UITapGestureRecognizer(target: self, action: #selector(incrementScoreTeam2))
    oneFingerTapButtonTeam2.numberOfTouchesRequired = 1
    buttonTeam2.addGestureRecognizer(oneFingerTapButtonTeam2)

    let twoFingerTapButtonTeam2 = UITapGestureRecognizer(target: self, action: #selector(decrementScoreTeam2))
    twoFingerTapButtonTeam2.numberOfTouchesRequired = 2
    buttonTeam2.addGestureRecognizer(twoFingerTapButtonTeam2)
}

func incrementScoreTeam1() {
    print("1 tapped")
    let ind = setButtonTitleAndIncrement(index: index1, button: buttonTeam1)
    index1 = ind
}

func incrementScoreTeam2() {
    print("2 tapped")
    let ind = setButtonTitleAndIncrement(index: index2, button: buttonTeam2)
    index2 = ind
}

func decrementScoreTeam1() {
    print("1 Two tapped")
    let ind = setButtonTitleAndDecrement(index: index1, button: buttonTeam1)
    index1 = ind
}

func decrementScoreTeam2() {
    print("2 Two tapped")
    let ind = setButtonTitleAndDecrement(index: index2, button: buttonTeam2)
    index2 = ind
}

Solution

  • How about subclassing the UIButton and then adding index as a property of the button. Something along the lines of:

    import UIKit
    
    @IBDesignable class BaseButton: UIButton {
    
        var index = 0
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            setup()
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            setup()
        }
    
        override func prepareForInterfaceBuilder() {
            super.prepareForInterfaceBuilder()
            setup()
        }
    
        func setup() {
            let oneFingerTapButtonTeam1 = UITapGestureRecognizer(target: self, action: #selector(incrementScoreTeam))
            oneFingerTapButtonTeam1.numberOfTouchesRequired = 1
            addGestureRecognizer(oneFingerTapButtonTeam1)
    
            let twoFingerTapButtonTeam1 = UITapGestureRecognizer(target: self, action: #selector(decrementScoreTeam))
            twoFingerTapButtonTeam1.numberOfTouchesRequired = 2
            addGestureRecognizer(twoFingerTapButtonTeam1)
        }
    
        func incrementScoreTeam() {
            let ind = setButtonTitleAndIncrement(index: index, button: self)
            index = ind
        }
    
        func decrementScoreTeam() {
            let ind = setButtonTitleAndDecrement(index: index, button: self)
            index = ind
        }
    
        func setButtonTitleAndIncrement(index: Int, button: UIButton) -> Int {
            var index = index
            index += 25
            button.setTitle(String(index), for: .normal)
            return index
        }
    
        func setButtonTitleAndDecrement(index: Int, button: UIButton) -> Int {
            var index = index
            index -= 25
            button.setTitle(String(index), for: .normal)
            return index
        } 
    }