pickerView didSelectRow is inputting into the wrong UITextField - ios

I am trying to follow the following solution to having multiple UIPickerViews on the one UIViewController. They suggest that a tag for each of the UITextfield which I have done and able to implement the number of rows, title for row and number of components. However, I have reached a stumbling block when implementing the did select row. When I select the UITextField it highlights another UITextfield. Below is the code I have so far.
class DriverViewController: UIViewController {
var selectedTrack: String?
var firstDriver: String?
var secondDriver: String?
var thirdDriver: String?
let tracks = ["Melbourne", "Manama", "Shanghai", "Baku",
"Barcelona", "Monaco", "Montreal","Le Castellet","Spielberg",
"Silverstone","Hockenheim","Budapest","Francorchamps","Monza","Singapore","Sochi","Suzuka","Austin","Interlagos","Abu Dhabi"]
let drivers = ["Lewis Hamilton","Antonio Giovinazzi","Kimi Raikkonen","Charles Leclerc","Sebastian Vettel","Romain Grosjean","Kevin Magnussen","Lando Norris",
"Carlos Sainz","Valtteri Bottas","Sergio Perez","Lance Stroll","Pierre Gasly","Max Verstappen","Nico Hulkenberg","Daniel Ricciardo","Alexander Albon","Daniil Kvyat","Robert Kubica","George Russell"]
#IBOutlet weak var TrackTextField: UITextField!
#IBOutlet weak var firstTextField: UITextField!
#IBOutlet weak var secondTextField: UITextField!
#IBOutlet weak var thirdTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
createTrackPicker()
createDriverPicker()
createToolBar()
// Do any additional setup after loading the view.
}
func createTrackPicker() {
let trackPicker = UIPickerView()
trackPicker.tag = 0
trackPicker.delegate = self
TrackTextField.inputView = trackPicker
}
func createDriverPicker() {
let driverPicker = UIPickerView()
driverPicker.tag = 1
driverPicker.tag = 2
driverPicker.tag = 3
driverPicker.delegate = self
firstTextField.inputView = driverPicker
secondTextField.inputView = driverPicker
thirdTextField.inputView = driverPicker
}
func createToolBar() {
let toolBar = UIToolbar()
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(ViewController.dismissKeyboard))
toolBar.setItems([doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
TrackTextField.inputAccessoryView = toolBar
firstTextField.inputAccessoryView = toolBar
secondTextField.inputAccessoryView = toolBar
thirdTextField.inputAccessoryView = toolBar
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
/*
// 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.destination.
// Pass the selected object to the new view controller.
}
*/
}
extension DriverViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView.tag == 0 {
return tracks.count
} else {
return drivers.count
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView.tag == 0 {
return "\(tracks[row])"
} else {
return "\(drivers[row])"
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView.tag == 0 {
selectedTrack = tracks[row]
TrackTextField.text = selectedTrack
} else if pickerView.tag == 1 {
firstDriver = drivers[row]
firstTextField.text = firstDriver
} else if pickerView.tag == 2 {
secondDriver = drivers[row]
secondTextField.text = secondDriver
} else if pickerView.tag == 3 {
thirdDriver = drivers[row]
thirdTextField.text = thirdDriver
}
}
}
This is how it looks on the screen.

Look at your function:
func createDriverPicker() {
let driverPicker = UIPickerView()
driverPicker.tag = 1
driverPicker.tag = 2
driverPicker.tag = 3
driverPicker.delegate = self
firstTextField.inputView = driverPicker
secondTextField.inputView = driverPicker
thirdTextField.inputView = driverPicker
}
Think about what value the tag property has after this code is run keeping in mind that it can only have one value.
You either need to update the picker view's tag property each time a text field begins editing, or you should abandon the use of the tag and simply check which text field is currently the first responder. See UIPickerView for each text field with different arrays (Swift/Firebase) for an example of how this is done.

Related

incorrect array showing in UIPickerView

I have two UIPickerviews that appear on one ViewController. I have tried to follow the following tutorial.
I have followed the suggestion in that I have tagged each of the UITextFields (I have 4 in total). See the the image.
Below is the code for the UIPickerViews.
extension DriverViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView.tag == 0 {
return tracks.count
} else {
return drivers.count
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView.tag == 0 {
return "\(tracks[row])"
} else {
return "\(drivers[row])"
}
}
The problem I am having is that the tracks array appear on all of the UITextfields.
Below is the code for each of the Arrays and the title of the UIPickerView.
override func viewDidLoad() {
super.viewDidLoad()
tracks = ["Melbourne", "Manama", "Shanghai", "Baku",
"Barcelona", "Monaco", "Montreal","Le Castellet","Spielberg",
"Silverstone","Hockenheim","Budapest","Francorchamps","Monza","Singapore","Sochi","Suzuka","Austin","Interlagos","Abu Dhabi"]
drivers = ["Lewis Hamilton","Antonio Giovinazzi","Kimi Raikkonen","Charles Leclerc","Sebastian Vettel","Romain Grosjean","Kevin Magnussen","Lando Norris",
"Carlos Sainz","Valtteri Bottas","Sergio Perez","Lance Stroll","Pierre Gasly","Max Verstappen","Nico Hulkenberg","Daniel Ricciardo","Alexander Albon","Daniil Kvyat","Robert Kubica","George Russell"]
createTrackPicker()
createDriverPicker()
createToolBar()
// Do any additional setup after loading the view.
}
func createTrackPicker() {
let trackPicker = UIPickerView()
trackPicker.delegate = self
TrackTextField.inputView = trackPicker
}
func createDriverPicker() {
let driverPicker = UIPickerView()
driverPicker.delegate = self
firstTextField.inputView = driverPicker
secondTextField.inputView = driverPicker
thirdTextField.inputView = driverPicker
}
func createToolBar() {
let toolBar = UIToolbar()
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(ViewController.dismissKeyboard))
toolBar.setItems([doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
TrackTextField.inputAccessoryView = toolBar
firstTextField.inputAccessoryView = toolBar
secondTextField.inputAccessoryView = toolBar
thirdTextField.inputAccessoryView = toolBar
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
You forgot the tag.
func createDriverPicker() {
let driverPicker = UIPickerView()
driverPicker.tag = 1 // <—-

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.
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.
you can assign your selected value to particular text field by using textField delegate methods which is textFieldDidBeginediting which is called when textField did started begin editing
like
take one variable
var textFieldSelected = UITextField()
and then in
func textFieldDidBeginEditing(_ textField: UITextField) {
textFieldSelected = textField
}
by doing this you will get you selected textField
and when you done choosing from picker
func doneSelection(){
if textFieldSelected == yourTextField(in which you want to enter your data)
{
yourTextField.text = data you want to enter from picker
}
}

How to hide UIPIckerView when the user touches the row already selected

I have in my code more than one UIPickerView, and let's say that the user opens the PickerView unintentionally, but wants to keep the same row selected, as I do for when the user touches the already selected row, the selector hide?
I tried this: UIPicker detect tap / touch on currently selected row, but I could not make it work.
--- edit ---
I'll try to be more specific. I'm a beginner in programming and the Swift language.
This is my ViewController.swift
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var colorLabel: UILabel!
#IBOutlet weak var sizeLabel: UILabel!
#IBOutlet weak var colorButton: UIButton!
#IBOutlet weak var sizeButton: UIButton!
#IBOutlet weak var resultButton: UIButton!
#IBOutlet weak var colorPickerView: UIPickerView! = UIPickerView()
#IBOutlet weak var sizePickerView: UIPickerView! = UIPickerView()
var colorPickerData = ["Blue", "Red"]
var sizePickerData = ["Small", "Big"]
var descri = String()
var resultadoImagem = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
colorPickerView.isHidden = true
sizePickerView.isHidden = true
self.colorPickerView.delegate = self
self.colorPickerView.dataSource = self
self.sizePickerView.delegate = self
self.sizePickerView.dataSource = self
colorLabel.text = colorPickerData[0]
sizeLabel.text = sizePickerData[0]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView.tag == 1 {
return colorPickerData.count
} else if pickerView.tag == 2 {
return sizePickerData.count
}
return 0
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView.tag == 1 {
return "\(colorPickerData[row])"
} else if pickerView.tag == 2 {
return "\(sizePickerData[row])"
}
return ""
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView.tag == 1 {
colorLabel.text = colorPickerData[row]
colorPickerView.isHidden = true
} else if pickerView.tag == 2 {
sizeLabel.text = sizePickerData[row]
sizePickerView.isHidden = true
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
colorPickerView.isHidden = true
sizePickerView.isHidden = true
}
#IBAction func colorButton(_ sender: Any) {
colorPickerView.isHidden = !colorPickerView.isHidden
}
#IBAction func sizeButton(_ sender: Any) {
sizePickerView.isHidden = !sizePickerView.isHidden
}
#IBAction func resultButton(_ sender: Any) {
if (colorLabel.text == "Blue")
&& (sizeLabel.text == "Big") { resultadoImagem = UIImage(named: "blue-big.png")!; descri = "BLUE"}
else if (colorLabel.text == "Blue")
&& (sizeLabel.text == "Small") { resultadoImagem = UIImage(named: "blue-small.png)!; descri = "BLUE"}
else if (colorLabel.text == "Red")
&& (sizeLabel.text == "Big") { resultadoImagem = UIImage(named: "red-big.png")!; descri = "RED"}
else if (colorLabel.text == "Red")
&& (sizeLabel.text == "Small") { resultadoImagem = UIImage(named: "red-small.png")!; descri = "RED"}
self.performSegue(withIdentifier: "resultSegue", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "resultSegue" {
let DestViewController : SecondViewController = segue.destination as! SecondViewController
DestViewController.descText = descri
DestViewController.resultPhoto = resultadoImagem
}
}
}
This code works great, when I hit the "Result" button it goes to the SecondViewController and shows photo and description.
My difficulty is, the colorPickerView opens with the data "Blue" selected, just as the sizerPickerView opens with the data "Small" by default. I want pickerView to close/hide when the user touches the data that is already selected.
Conform class to UIGestureRecognizerDelegate protocol
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UIGestureRecognizerDelegate {
// ...
}
Add a UITapGestureRecognizer to your colorPickerView
let tap = UITapGestureRecognizer(target: self, action: #selector(self.tapAction(_:)))
tap.cancelsTouchesInView = false
tap.delegate = self
colorPickerView.addGestureRecognizer(tap)
Implement UIGestureRecognizerDelegate method
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
Finally implement tapAction
func tapAction(_ tapRecognizer:UITapGestureRecognizer) {
if tapRecognizer.state == .ended {
let rowHeight : CGFloat = colorPickerView.rowSize(forComponent: 0).height
let selectedRowFrame: CGRect = colorPickerView.bounds.insetBy(dx: 0.0, dy: (colorPickerView.frame.height - rowHeight) / 2.0)
let userTappedOnSelectedRow = selectedRowFrame.contains(tapRecognizer.location(in: colorPickerView))
if (userTappedOnSelectedRow){
let selectedRow = colorPickerView.selectedRow(inComponent: 0)
//do whatever you want here
}
}
}
Replicate steps 2 and 4 using sizerPickerView to extend functionality.

UIPickers data will not display from UITextField

I am new to Swift but I feel like I'm picking it up pretty well.
I have four UITextField with InputView's that display UIPickerViews, and I programatically placed them within the app. My code shows no errors, all UIPickerViews pop up (picker, picker2, picker3, picker4), but only the array from "climate" shows in all four views. So my obvious issue is... how in the world do I get the remaining arrays (environment, region, budget) to display in their respected UIPickerViews!
also, side request, how would I disable the text field so that no one could be able to paste anything into the text field
Here is my code:
import UIKit
class ViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {
#IBOutlet weak var climateText: UITextField!
#IBOutlet weak var environmentText: UITextField!
#IBOutlet weak var regionText: UITextField!
#IBOutlet weak var budgetText: UITextField!
var picker = UIPickerView()
var picker2 = UIPickerView()
var picker3 = UIPickerView()
var picker4 = UIPickerView()
//MARK: Arrays for PickerViews
var climates = ["Hot","Warm","Cold","Anywhere"]
var environment = ["Beach","City","Mountain","Rural","Anywhere"]
var region = ["Central America","Carribean","Europe","North America","South America","Anywhere"]
var budget = ["$0-500","$501-1000","$1001-1500","$1501-2500","$2501 and up"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
picker.tag = 0
picker2.tag = 1
picker3.tag = 2
picker4.tag = 3
picker.delegate = self
picker2.delegate = self
picker3.delegate = self
picker4.delegate = self
picker.dataSource = self
picker2.dataSource = self
picker3.dataSource = self
picker4.dataSource = self
climateText.inputView = picker
environmentText.inputView = picker2
regionText.inputView = picker3
budgetText.inputView = picker4
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if picker.tag == 0 {
return climates.count
} else if picker2.tag == 1 {
return environment.count
} else if picker3.tag == 2 {
return region.count
} else if picker4.tag == 3 {
return budget.count
}
return 1
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if picker.tag == 0 {
return climates[row]
} else if picker2.tag == 1 {
return environment[row]
} else if picker3.tag == 2 {
return region[row]
} else if picker4.tag == 3 {
return budget[row]
}
return ""
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if picker.tag == 0 {
climateText.text = climates[row]
} else if picker2.tag == 1 {
environmentText.text = environment[row]
} else if picker3.tag == 2 {
regionText.text = region[row]
} else if picker4.tag == 3 {
budgetText.text = budget[row]
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I'm not a fan of using tags (see point 2 here), but to get you past this problem, change your didSelectRow function to do this instead:
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView.tag == 0 {
climateText.text = climates[row]
} else if pickerView.tag == 1 {
environmentText.text = environment[row]
} else if pickerView.tag == 2 {
regionText.text = region[row]
} else if pickerView.tag == 3 {
budgetText.text = budget[row]
}
}
Your problem simply was that you weren't looking to see the tag from the picker view the user just made a section with.

Swift PickerViews issue

I'm taking my first baby steps in Swift and I want to make a conversor app.
I want to use 2 pickerviews, one for choose the origin type and the other to choose the destination type.
The problem is that I can't make the 2 pickerviews work... What I want is click in one textfield and show the first pickerview and then click in other textfield and show the other pickerview but what is happening is that it always opening the first pickerview.
Here's the code:
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
#IBOutlet weak var txtOrigem: UITextField!
#IBOutlet weak var txtDestino: UITextField!
#IBOutlet weak var pickerpeso: UIPickerView! = UIPickerView()
#IBOutlet weak var pickerpeso2: UIPickerView! = UIPickerView()
var pesos = ["Escolher Opção","Gramas", "Quilogramas", "Toneladas", "Libras", "Onças"]
var pesos2 = ["ola","Gramas", "Quilogramas", "Toneladas", "Libras", "Onças"]
override func viewDidLoad() {
super.viewDidLoad()
pickerpeso.delegate = self
pickerpeso2.delegate = self
txtOrigem.delegate = self
txtDestino.delegate = self
pickerpeso.tag = 0
pickerpeso2.tag = 1
pickerpeso.hidden = true;
pickerpeso2.hidden = true;
txtOrigem.text = pesos[0]
txtDestino.text = pesos2[0]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView.tag == 0 {
return pesos.count
}
else if pickerView.tag == 1 {
return pesos2.count
}
return 1
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView.tag == 0 {
return pesos[row]
}
else if pickerView.tag == 1 {
return pesos2[row]
}
return ""
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView.tag == 0 {
txtOrigem.text = pesos[row]
}
else if pickerView.tag == 1 {
txtDestino.text = pesos2[row]
}
pickerpeso.hidden = true
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
pickerpeso.hidden = false
return false
}
}
Hope someone could help me. Sorry for my poor English.
Thanks in advance!
The problem is your textFieldShouldBeginEditing method. You are just setting the .hidden property for one of the pickerViews. Add tags to both of your textFields (like 2 and 3) and change the method to this:
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if textField.tag == 2 {
pickerpeso.hidden = false
pickerpeso2.hidden = true
} else if textField.tag == 3 {
pickerpeso.hidden = true
pickerpeso2.hidden = false
}
return false
}
Dependent on which textField will get the focus one pickerView is hidden and the other one is visible.

Resources