Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIPickerView for each text field with different arrays (Swift/Firebase)

I am trying to create a form in which each text field has a UIPickerView which the user can use to select the option needed. I need a to use a different array of information for each text field but I can't seem to get it to work and I have been stuck on it for quite a while now.

I have had a method which was possibly working but I couldn't then retrieve the data from the text field for Firebase due to each field having the same name.

Here is my code so far, this is the latest method that I have tried that doesn't work:

import UIKit
import Firebase
import FirebaseDatabase

class CreatePostViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate {

@IBOutlet weak var gameTextField: UITextField!
@IBOutlet weak var activityTextField: UITextField!
@IBOutlet weak var consoleTextField: UITextField!
@IBOutlet weak var skillTextField: UITextField!
@IBOutlet weak var communicationTextField: UITextField!
@IBOutlet weak var lfglfmTextField: UITextField!
@IBOutlet weak var rulesTextView: UITextView!
@IBOutlet weak var descriptionTextView: UITextView!

var games = ["Assassin's Creed Origins", "Battlefield 1", "Call of Duty: Advanced Warfare", "Call of Duty: Black Ops III", "Call of Duty: Ghosts", "Call of Duty: Infinite Warfare", "Call of Duty: Modern Warfare Remastered", "Call of Duty: WWII", "Destiny", "Destiny 2", "Fifa 16", "Fifa 17", "Fifa 18", "Rocket League"]
var console = ["Xbox One", "Xbox 360", "Playstation 4", "Playstation 3"]
var skill = ["Achiever", "Explorer", "Killer", "Socializer"]
var communication = ["Mic", "No Mic"]
var lfglfm = ["LFG", "LFM"]

var itemSelected = ""

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    //remove margin / padding from textview
    self.rulesTextView.textContainerInset = .zero
    self.rulesTextView.contentInset = UIEdgeInsetsMake(0, -5, 0, 0)
//        self.descriptionTextView.textContainerInset = .zero
//        self.descriptionTextView.contentInset = UIEdgeInsetsMake(0, -5, 0, 0)

    //allow tap on screen to remove text field input from screen
    self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))

    //UIPICKER
    let pickerView = UIPickerView()
    pickerView.delegate = self
    pickerView.dataSource = self

    gameTextField.inputView = pickerView
    consoleTextField.inputView = pickerView
    skillTextField.inputView = pickerView
    communicationTextField.inputView = pickerView
    lfglfmTextField.inputView = pickerView

    updatePicker()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

//update pickerView
func updatePicker(){
    let pickerView = UIPickerView()
    pickerView.reloadAllComponents()
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    if gameTextField.isFirstResponder{
        return games.count
    }else if consoleTextField.isFirstResponder{
        return console.count
    }else if skillTextField.isFirstResponder{
        return skill.count
    }else if communicationTextField.isFirstResponder{
        return communication.count
    }else if lfglfmTextField.isFirstResponder{
        return lfglfm.count
    }
}

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
    if gameTextField.isFirstResponder{
        return games[row]
    }else if consoleTextField.isFirstResponder{
        return console[row]
    }else if skillTextField.isFirstResponder{
        return skill[row]
    }else if communicationTextField.isFirstResponder{
        return communication[row]
    }else if lfglfmTextField.isFirstResponder{
        return lfglfm[row]
    }
}

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    if gameTextField.isFirstResponder{
        let itemselected = games[row]
        gameTextField.text = itemselected
    }else if consoleTextField.isFirstResponder{
        let itemselected = console[row]
        consoleTextField.text = itemselected
    }else if skillTextField.isFirstResponder{
        let itemselected = skill[row]
        skillTextField.text = itemselected
    }else if communicationTextField.isFirstResponder{
        let itemselected = communication[row]
        communicationTextField.text = itemselected
    }else if lfglfmTextField.isFirstResponder{
        let itemselected = lfglfm[row]
        lfglfmTextField.text = itemselected
    }
}


@IBAction func createPostTapped(_ sender: UIButton) {
    if let uid = Auth.auth().currentUser?.uid {
        Database.database().reference().child("usernames").child(uid).observeSingleEvent(of: .value, with: {
            (snapshot) in
            if let userDictionary = snapshot.value as? [String: AnyObject] {
                for user in userDictionary {
                    if let username = user.value as? String {
                        if let game = self.gameTextField.text {
                            if let activity = self.activityTextField.text {
                                if let console = self.consoleTextField.text {
                                    if let skill = self.skillTextField.text {
                                        if let communication = self.communicationTextField.text {
                                            if let lfglfm = self.lfglfmTextField.text {
                                                if let description = self.descriptionTextView.text {

                                                    let postObject: Dictionary<String, Any> = [
                                                        "uid" : uid,
                                                        "username" : username,
                                                        "game" : game,
                                                        "activity" : activity,
                                                        "console" : console,
                                                        "skill" : skill,
                                                        "communication" : communication,
                                                        "lfglfm" : lfglfm,
                                                        "description" : description
                                                        ]

                                                    Database.database().reference().child("posts").childByAutoId().setValue(postObject)

                                                    let alert = UIAlertController(title: "Success!", message: "Your post was added successfully.", preferredStyle: .alert)
                                                    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
                                                        //code will run when ok button is pressed
                                                        let vc = self.storyboard?.instantiateViewController(withIdentifier: "LoggedInVC")
                                                        self.present(vc!, animated: true, completion: nil)
                                                    }))
                                                    self.present(alert, animated: true, completion: nil)

                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        })
    }
}



/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}

If anyone knows of a successful method which I can implement please feel free contribute it would be much appreciated.

Thank you.

like image 599
Daniel Jones Avatar asked Jan 03 '23 22:01

Daniel Jones


1 Answers

Your code is almost right. I would just store a class attribute with the UIPickerView so you can reload the components upon textField editing status change. For that purpose, you have also to set the textField delegates.

Here a working example with the adjustments I just commented:

import UIKit

class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate {


    @IBOutlet weak var gameTextField: UITextField!
    @IBOutlet weak var activityTextField: UITextField!
    @IBOutlet weak var consoleTextField: UITextField!
    @IBOutlet weak var skillTextField: UITextField!
    @IBOutlet weak var communicationTextField: UITextField!
    @IBOutlet weak var lfglfmTextField: UITextField!

    var games = ["Assassin's Creed Origins", "Battlefield 1", "Call of Duty: Advanced Warfare", "Call of Duty: Black Ops III", "Call of Duty: Ghosts", "Call of Duty: Infinite Warfare", "Call of Duty: Modern Warfare Remastered", "Call of Duty: WWII", "Destiny", "Destiny 2", "Fifa 16", "Fifa 17", "Fifa 18", "Rocket League"]
    var console = ["Xbox One", "Xbox 360", "Playstation 4", "Playstation 3"]
    var skill = ["Achiever", "Explorer", "Killer", "Socializer"]
    var communication = ["Mic", "No Mic"]
    var lfglfm = ["LFG", "LFM"]

    var itemSelected = ""

    weak var pickerView: UIPickerView?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        //remove margin / padding from textview
        //        self.descriptionTextView.textContainerInset = .zero
        //        self.descriptionTextView.contentInset = UIEdgeInsetsMake(0, -5, 0, 0)

        //allow tap on screen to remove text field input from screen
        self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))

        //UIPICKER
        let pickerView = UIPickerView()
        pickerView.delegate = self
        pickerView.dataSource = self

        gameTextField.delegate = self
        consoleTextField.delegate = self
        skillTextField.delegate = self
        communicationTextField.delegate = self
        lfglfmTextField.delegate = self

        gameTextField.inputView = pickerView
        consoleTextField.inputView = pickerView
        skillTextField.inputView = pickerView
        communicationTextField.inputView = pickerView
        lfglfmTextField.inputView = pickerView

        //It is important that goes after de inputView assignation
        self.pickerView = pickerView

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {
        self.pickerView?.reloadAllComponents()
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if gameTextField.isFirstResponder{
            return games.count
        }else if consoleTextField.isFirstResponder{
            return console.count
        }else if skillTextField.isFirstResponder{
            return skill.count
        }else if communicationTextField.isFirstResponder{
            return communication.count
        }else if lfglfmTextField.isFirstResponder{
            return lfglfm.count
        }
        return 0
    }

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

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if gameTextField.isFirstResponder{
            return games[row]
        }else if consoleTextField.isFirstResponder{
            return console[row]
        }else if skillTextField.isFirstResponder{
            return skill[row]
        }else if communicationTextField.isFirstResponder{
            return communication[row]
        }else if lfglfmTextField.isFirstResponder{
            return lfglfm[row]
        }
        return nil
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if gameTextField.isFirstResponder{
            let itemselected = games[row]
            gameTextField.text = itemselected
        }else if consoleTextField.isFirstResponder{
            let itemselected = console[row]
            consoleTextField.text = itemselected
        }else if skillTextField.isFirstResponder{
            let itemselected = skill[row]
            skillTextField.text = itemselected
        }else if communicationTextField.isFirstResponder{
            let itemselected = communication[row]
            communicationTextField.text = itemselected
        }else if lfglfmTextField.isFirstResponder{
            let itemselected = lfglfm[row]
            lfglfmTextField.text = itemselected
        }
    }



    /*
     // MARK: - Navigation

     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     // Get the new view controller using segue.destinationViewController.
     // Pass the selected object to the new view controller.
     }
     */

}

EDITED:

You don't need the updatePicker method. It does nothing indeed. I've deleted the createPostTapped method for the purpose of this simple example.

like image 54
alujan Avatar answered Jan 05 '23 15:01

alujan