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]
    }

Replies

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
    }
}
  • TapGesture will activate when you tap anywhere in the picker, on a row which may be different from selection, isn't it ? And tapping will not change the selection. That could be misleading. Or pickerTapped must first identify which row was tapped, which is not so easy. Or limit the tap to the center of the picker which is where the selection is.

Add a Comment