How to tap a row in a UIPickerView

I am trying to get the value of a tapered row in a UIPickerView but every time I scroll through it, it gives me every value I go through. How can I get the value of when the user taps the row?

I am trying to append the value that the user clicks on to an array called squaresTaken.

func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        pickerData.count
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        intToString()
        return pickerData[row]
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        squaresTaken.append(Int(pickerData[row])!)
        yourSquare.text = pickerData[row]
    }

I scroll through it, it gives me every value 

You mean each time you scroll and stop scrolling ? That's the normal behaviour.

And there is no API (AFAIK) to detect user tap on a row.

What you could do:

  • add a "Select" button, just above or on the side of the picker
  • create a var in the class :
var lastSelection : Int?
  • change
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        squaresTaken.append(Int(pickerData[row])!)
        yourSquare.text = pickerData[row]
    }

into

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        lastSelection = row
    }

Do it in the button IBAction

@IBAction selectFromPicker(_ sender: UIButton) {

    if let selection = lastSelection {
         squaresTaken.append(Int(pickerData[selection])!)
        yourSquare.text = pickerData[selection]
    }
  // If you close the picker, hide the button as well
}

How can I get the value of when the user taps the row?

If you do not like adding a "Select" button, you can add a UITapGestureRecognizer to the UIPickerView.

Something like this:

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var picker: UIPickerView!
    @IBOutlet weak var yourSquare: UILabel!
    
    var pickerData: [String] = [
        "10", "20", "30"
    ]
    
    var squaresTaken: [Int] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        picker.delegate = self
        picker.dataSource = self
        let tap = UITapGestureRecognizer(target: self, action: #selector(pickerTapped))
        tap.delegate = self
        picker.addGestureRecognizer(tap)
    }
    
    func intToString() {
        //???
    }
    
    @objc func pickerTapped(_ gestureRecognizer: UITapGestureRecognizer) {
        guard let pickerView = gestureRecognizer.view as? UIPickerView else {
            return
        }
        let row = pickerView.selectedRow(inComponent: 0)
        squaresTaken.append(Int(pickerData[row])!)
        yourSquare.text = pickerData[row]
    }
}

extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {
    
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        pickerData.count
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        intToString()
        return pickerData[row]
    }
    
}

extension ViewController: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}
How to tap a row in a UIPickerView
 
 
Q