Search code examples
swiftuitextfielduipickerview

UIPickerView Multiple rows display in UITextField


I am trying to display my UIPickerView in a TextField, I have done it so it displays one of the rows but not all of them.

Here is my code:

class ViewController: UIViewController {

static var isAlreadyLaunchedOnce = false
var ref: DatabaseReference!


    @IBOutlet weak var txtDate: UITextField!


    @IBOutlet weak var inputpickerdate: UIPickerView!



    var pickerDate: [[String]] = [[String]] ()


    var selected: String?

    override func viewDidLoad() {
        super.viewDidLoad()

    self.inputpickerdate.delegate = self
    self.inputpickerdate.dataSource = self

        pickerDate = [["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"], ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"]]

        if FirebaseApp.app() == nil {
            FirebaseApp.configure()
        }



}

extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {

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

    return 3

    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
            //return pickerList.count
        return pickerDate [component].count

        }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

        return pickerDate [component] [row]

   }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        txtDate.text = pickerDate[component][row]
        self.view.endEditing(false)

    }

    }

In the textview I only see the month not the full date, I want to show something like:

mon day year

Not sure how to do this, basically needs to show all rows not just one.


Solution

  • The reason is that you are are setting the text in your UITextField only to the text of the component you are selecting pickerDate[component][row].

    There are multiple ways you could achieve what you want to do with a UIPicker, albeit quite convoluted...

    e.g.

    • You could have three labels, one for each component.
    • You could persist the selection of each component, then build up a string from the persisted values.

    A much better way to pick dates would be to use a UIDatePicker instead.

    class ViewController: UIViewController {
    
        @IBOutlet weak var txtDate: UITextField!
        @IBOutlet weak var datepicker: UIDatePicker!
    
        let dateFormatter = DateFormatter()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            dateFormatter.dateStyle = .medium
            datepicker.addTarget(self, action: #selector(dateChanged(_:)), for: .valueChanged)
        }
    
        @objc func dateChanged(_ sender: UIDatePicker) {
            txtDate.text = dateFormatter.string(from: sender.date)
        }
    }
    

    If you do want to go down the route of using a UIPickerView you could persist the value of each component and use those values to build up the string you want to display.

    class ViewController: UIViewController {
    
        @IBOutlet weak var txtDate: UILabel!
        @IBOutlet weak var picker: UIPickerView!
    
        let pickerData: [[String]] = [
            ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
            ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"],
            ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"]
        ]
    
        var weekDay: String = ""
        var dayOfMonth: String = ""
        var month: String = ""
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.picker.delegate = self
            self.picker.dataSource = self
    
            // Give the label a default value
            weekDay = pickerData[0][0]
            dayOfMonth = pickerData[1][0]
            month = pickerData[2][0]
    
            updateDateText()
        }
    
        func updateDateText() {
            txtDate.text = "\(weekDay) \(dayOfMonth) \(month)"
        }
    }
    
    extension ViewController: UIPickerViewDataSource {
    
        func numberOfComponents(in pickerView: UIPickerView) -> Int {
            return pickerData.count
        }
    
        func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
            return pickerData [component].count
        }
    }
    
    extension ViewController: UIPickerViewDelegate {
    
        func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
            return pickerData[component][row]
        }
    
        func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
            switch component {
            case 0:
                weekDay = pickerData[component][row]
            case 1:
                dayOfMonth = pickerData[component][row]
            case 2:
                month = pickerData[component][row]
            default:
                break
            }
    
            updateDateText()
        }
    }