2

I have a weird problem but I guess you guys can show me the mistake pretty easy. I am using a picker view for multiple text fields. But it only shows the "last array" for every text field and pushes on top of everything the selected row in the last text field. Therefore it seems that every text field controls only the last text field.

Here is the involved code, hope you guys can help me:

class SignUpViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {




    //Mark: Properties


    @IBOutlet weak var genderPicker: UITextField!
    @IBOutlet weak var branchePicker: UITextField!
    @IBOutlet weak var countryPicker: UITextField!




    // Picker View Arrays
    let genders = ["male", "female", "non-binary"]
    let branches = ["Advertising", "Architecture", "Design: Product", "Design: Graphic", "Design: Fashion", "Design: Others", "Film/ Video & TV", "IT", "Museums & Galleries", "Music", "Photography", "Performing & Visual Arts", "Radio", "Others"]
    let countries = ["Austria", "Australia", "USA", "Germany"]

    // Picker View
    var pickerViewSignUp = UIPickerView()



    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.





        // Pickers

        pickerViewSignUp.delegate = self
        pickerViewSignUp.dataSource = self


        // Delegates
        genderPicker.textAlignment = .center
        genderPicker.inputView = pickerViewSignUp
        genderPicker.placeholder = "Select Gender"

        branchePicker.textAlignment = .center
        branchePicker.inputView = pickerViewSignUp
        branchePicker.placeholder = "Select Branch"

        countryPicker.textAlignment = .center
        countryPicker.inputView = pickerViewSignUp
        countryPicker.placeholder = "Select Country"



    }


    // Mark: PickerViews
            // List of the SignUp used Drop Down Items

            // TextField delegate

    func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {

        pickerViewSignUp.reloadAllComponents()

             return true
         }


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

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {

        if pickerViewSignUp == genderPicker {
            return genders.count

        }   else if pickerViewSignUp == branchePicker {
            return branches.count

        } else {return countries.count}

    }


    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if pickerViewSignUp == genderPicker {
            return genders[row]
        } else if  pickerViewSignUp == branchePicker {
            return branches[row] } else {return countries[row]}
    }


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

        if pickerViewSignUp == genderPicker {
            genderPicker.text = genders[row]
        } else if pickerViewSignUp == branchePicker {
            branchePicker.text = branches[row]
        } else {countryPicker.text = countries[row]}
    }

}
7
  • Look here at pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int): pickerViewSignUp == genderPicker and so on... you are comparing a UITextField with a UIPickerView... it's always false. Commented Mar 2, 2020 at 13:26
  • Thanks for that fast answer! Could you maybe give me a hint how to do it better though? :) Commented Mar 2, 2020 at 13:32
  • @Schaedel420 Do you want the "genders array" to be displayed if you tap on a specific button? And another array to be displayed if you tap on another button? Commented Mar 2, 2020 at 13:34
  • Exactly @Putte when clicking on "Gender" the Pickerview should let the User select Gender... Afterwards he should select his branch, country and so on.... Commented Mar 2, 2020 at 13:35
  • I'd suggest using 3 bools for the comparing. Commented Mar 2, 2020 at 13:36

2 Answers 2

1

This is my solution... use an enum to track the selected state and add UITextFieldDelegates:

class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {


//Mark: Properties
@IBOutlet weak var genderPicker: UITextField!
@IBOutlet weak var branchePicker: UITextField!
@IBOutlet weak var countryPicker: UITextField!

enum TextFieldType {
    case gender
    case branche
    case country
    case none
}

// Picker View Arrays
let genders = ["male", "female", "non-binary"]
let branches = ["Advertising", "Architecture", "Design: Product", "Design: Graphic", "Design: Fashion", "Design: Others", "Film/ Video & TV", "IT", "Museums & Galleries", "Music", "Photography", "Performing & Visual Arts", "Radio", "Others"]
let countries = ["Austria", "Australia", "USA", "Germany"]

// Picker View
var pickerViewSignUp = UIPickerView()
var selectedPikerType =  TextFieldType.none

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.


    // Pickers

    pickerViewSignUp.delegate = self
    pickerViewSignUp.dataSource = self


    // Delegates
    genderPicker.textAlignment = .center
    genderPicker.inputView = pickerViewSignUp
    genderPicker.placeholder = "Select Gender"
    genderPicker.delegate = self

    branchePicker.textAlignment = .center
    branchePicker.inputView = pickerViewSignUp
    branchePicker.placeholder = "Select Branch"
    branchePicker.delegate = self

    countryPicker.textAlignment = .center
    countryPicker.inputView = pickerViewSignUp
    countryPicker.placeholder = "Select Country"
    countryPicker.delegate = self
}


// Mark: PickerViews
        // List of the SignUp used Drop Down Items

        // TextField delegate


func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {

    switch textField {
    case genderPicker: selectedPikerType    = .gender
    case branchePicker: selectedPikerType   = .branche
    case countryPicker: selectedPikerType   = .country
    default: selectedPikerType              = .none
    }


    pickerViewSignUp.reloadAllComponents()

    return true
}


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

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {

    switch selectedPikerType {
    case .branche   : return branches.count
    case .country   : return countries.count
    case .gender    : return genders.count
    case .none      : return 0
    }

}

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

    switch selectedPikerType {
    case .branche   : return branches[row]
    case .country   : return countries[row]
    case .gender    : return genders[row]
    case .none      : return nil
    }
}

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

    switch selectedPikerType {
    case .branche   : branchePicker.text = branches[row]
    case .country   : countryPicker.text = countries[row]
    case .gender    : genderPicker.text = genders[row]
    case .none      : break
    }
}

}

I'd also suggest you a better naming of the variables... If the object is a textfield use the prefix "txt" ... so txtGender and so on. It is way clearer. Use also extensions to split datasources and delegates it makes it all more readable. :)

You can write an extension like this:

extension ViewController: UITextFieldDelegate {

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {

       switch textField {
       case genderPicker: selectedPikerType    = .gender
       case branchePicker: selectedPikerType   = .branche
       case countryPicker: selectedPikerType   = .country
       default: selectedPikerType              = .none
       }


       pickerViewSignUp.reloadAllComponents()

       return true
   }

}

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for that fast answer! Highly appreciate it... the problem is @DungeonDev that for the gender/branche and country .delegate = self i get : Cannot assign value of type 'SignUpViewController' to type 'UITextFieldDelegate?'
and that's also a good hint with the prefix and extensions!! Thanks :)
I've edited the answer to show you how to use extensions.
It's working! Thanks so much you guys are all legends! Thanks for the fast help to all of you guys! :)
0

Have a global textField variable in your class to get the instance of textField you are editing and assign the value when editing.

In the pickerView delegate and datasource methods do the comparison between the current textField and the rest of the textField elements. It should work.

Below is the code for your reference:

class SignupViewController {

var currentTextfield: UITextField?

// Mark: PickerViews
// List of the SignUp used Drop Down Items

// TextField delegate

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    currentTextfield = textField
    pickerViewSignUp.reloadAllComponents()
    return true
}


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

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    switch currentTextfield {
    case genderPicker:
        return genders.count
    case branchePicker:
        return branches.count
    default
        return countries.count
    }
}

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.