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.
Related
Im trying to use two pickerviews on two different textboxes (i align them underneath the textboxes and hide them until called). I hide the pickerviews until i'm ready to use and tie both textboxes to their corresponding textbox. The first pickerview works fine, but when i click on the second, my list doesnt appear and it appears still hidden. I've read thru the code multiple times and cannot find the issue and have watched multiple videos and checked apples documentation to no avail. Code posted below for review and help. Thanks in advance!
class fifthViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
#IBOutlet weak var heightInput: UITextField!
#IBOutlet weak var weightInput: UITextField!
#IBOutlet weak var bmiOutput: UITextField!
#IBOutlet weak var weightPicker: UIPickerView!
#IBOutlet weak var heightPicker: UIPickerView!
var height = ["48", "49", "50"]
var weight = ["90", "91", "92"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
var countrows : Int = height.count
if pickerView == weightPicker {
countrows = self.weight.count
}
return countrows
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == heightPicker {
let titleRow = height[row]
return titleRow
}
else if pickerView == weightPicker {
let titleRow = weight[row]
return titleRow
}
return ""
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == heightPicker {
self.heightInput.text = self.height[row]
self.heightPicker.isHidden = true
}
else if pickerView == weightPicker {
self.weightInput.text = self.weight[row]
self.weightPicker.isHidden = true
}
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if (textField == self.heightInput) {
self.heightPicker.isHidden = false
}
else if (textField == self.weightInput) {
self.weightInput.isHidden = false
}
}```
In textFieldDidBeginEditing(), you need to set self.weightPicker.isHidden to false instead of self.weightInput.isHidden.
func textFieldDidBeginEditing(_ textField: UITextField) {
if (textField == self.heightInput) {
self.heightPicker.isHidden = false
}
else if (textField == self.weightInput) {
self.weightPicker.isHidden = false
}
}
Modify your code to use inputViews
I agree with #PaulW11's comment:
"You would be almost certainly better off if you made the picker views
the inputView of each text field."
Here are the changes you need for a basic setup. Get rid of the pickers in the Storyboard and disconnect the #IBOutlet connections.
Then add these modifications:
// These are no longer outlets since they're created in code
var weightPicker: UIPickerView!
var heightPicker: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
// set up the picker views
self.weightPicker = UIPickerView()
self.weightPicker.delegate = self
self.weightPicker.dataSource = self
self.heightPicker = UIPickerView()
self.heightPicker.delegate = self
self.heightPicker.dataSource = self
self.heightInput.inputView = self.heightPicker
self.weightInput.inputView = self.weightPicker
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == heightPicker {
self.heightInput.text = self.height[row]
// make picker go away after value has been selected
self.heightInput.resignFirstResponder()
}
else if pickerView == weightPicker {
self.weightInput.text = self.weight[row]
// make picker go away after value has been selected
self.weightInput.resignFirstResponder()
}
}
My pickerview is not displaying for some reason even after reloading all components. I click start and it just does not load up the pickerview as I want this to load and then you can select an option and go to the next question?
import UIKit
class QuestionsViewController: UIViewController, UIPickerViewDelegate {
#IBOutlet weak var Next: UIButton!
#IBOutlet weak var pickerview: UIPickerView!
#IBOutlet weak var itemLabel: UILabel!
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var Question: UILabel!
#IBAction func Next(_ sender: Any) {
cQuestion.currentQuestion = cQuestion.currentQuestion + 1
pickerview.reloadAllComponents()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//var LabelText: String = ""
//var arrayOfQuestions: [String] = ["&","&&","||","None of above"]
//var correctAns:String = ""
//var currentQuestion = 0
let cQuestion = Questions()
//init(arrayOfQuestions:String, correctAns:String, LabelText:String) {
//self.arrayOfQuestions = [arrayOfQuestions]
// self.correctAns = correctAns
// self.LabelText = LabelText
//}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
itemLabel.text = cQuestion.arrayOfQuestions[0]
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
if(cQuestion.currentQuestion == 0) {
Question.text = "Q1. Which is a logical OR operator"
return cQuestion.arrayOfQuestions.count
} else if (cQuestion.currentQuestion == 1) {
Question.text = "Q2. Compiler generates_file"
return cQuestion.arrayOfQuestions.count
}
hide()
Question.text = "You have finished"
Next.isHidden = true
return cQuestion.arrayOfQuestions.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?{
if(cQuestion.currentQuestion == 0) {
return cQuestion.arrayOfQuestions[row]
} else if (cQuestion.currentQuestion == 1) {
return cQuestion.arrayOfQuestions[row]
}
return cQuestion.arrayOfQuestions[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int){
if (cQuestion.currentQuestion == 0) {
let itemSelected = cQuestion.arrayOfQuestions[row]
itemLabel.text = itemSelected
} else if (cQuestion.currentQuestion == 1) {
let itemSelected = cQuestion.arrayOfQuestions[row]
itemLabel.text = itemSelected
}
}
func hide() {
pickerview.isHidden = true
itemLabel.isHidden = true
}
}
My guess: it looks like as soon as numberOfRowsInComponent is called (which it does as soon as it prepares to be added to the view) you also call hide() which in turns seems to set your pickerView to isHidden = true. I don't see anywhere in your code where isHidden is subsequently set to false.
If that happens to not be the case, also check what the value of pickerview.dataSource is to make sure it's not nil.
I am having an error in the "pickerview.reloadAllComponents()" and I cannot get into the 2nd question as there is an error which states
fatal error: unexpectedly found nil while unwrapping an Optional value
import UIKit
class QuestionsViewController: UIViewController, UIPickerViewDelegate {
#IBOutlet weak var Next: UIButton!
#IBOutlet weak var itemLabel: UILabel!
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var Question: UILabel!
#IBOutlet weak var pickerview: UIPickerView!
let cQuestion = Questions()
public var q1: [String] = ["&","&&","||","None of above"]
public var q2: [String] = ["&","&&","||","hello"]
#IBAction func NextAction(_ sender: Any){
cQuestion.currentQuestion = cQuestion.currentQuestion + 1
pickerview.reloadAllComponents()
}
override func viewDidLoad() {
label1.text = cQuestion.LabelText
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
itemLabel.text = cQuestion.q1[0]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
var qcount: Int = 0
if(cQuestion.currentQuestion == 0) {
Question.text = "Q1. Which is a logical OR operator"
qcount = cQuestion.q1.count
} else if (cQuestion.currentQuestion == 1) {
Question.text = "Q2. Compiler generates_file"
qcount = cQuestion.q2.count
} else {
hide()
Question.text = "You have finished"
Next.isHidden = true
}
//if(currentQuestion == 0) {
//Question.text = "Q1. Which is a logical OR operator"
//return q1.count
//} else if (currentQuestion == 1) {
//Question.text = "Q2. Compiler generates_file"
//return q2.count
//}
//hide()
//Question.text = "You have finished"
//Next.isHidden = true
//return q1.count
return qcount
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?{
if(cQuestion.currentQuestion == 0) {
return q1[row]
} else if (cQuestion.currentQuestion == 1) {
return q2[row]
}
return q1[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int){
if (cQuestion.currentQuestion == 0) {
let itemSelected = q1[row]
itemLabel.text = itemSelected
} else if (cQuestion.currentQuestion == 1) {
let itemSelected = q2[row]
itemLabel.text = itemSelected
}
}
func hide() {
pickerview.isHidden = true
itemLabel.isHidden = true
}
}
I think you have IBOutlet of pickerview is not connected properly, Make sure you need to check in Storyboard or Xib pickerview is connected properly or not?
i hope it will work for you
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.
I have a test project I am using to develop my code before I implement it in my real project. In the test, I have two fields that when tapped should bring up a dataPicker populated with the array for that field. This works fine for the first field (enterSeason) but the second (enterSport) returns just the keyboard. I have walked through the debugger and the variable are correct and the working the same for both fields. What am I missing? Thank you.
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
#IBOutlet var enterSeason: UITextField!
#IBOutlet var enterSport: UITextField!
var dataPickerView = UIPickerView()
var season = ["2013", "2014", "2015"] //multi-season
//var season = ["2015"] //single-season
var sport = ["Baeball", "Football", "Basketball", "Hockey"]
var activeDataArray = []
override func viewDidLoad() {
super.viewDidLoad()
enterSeason.inputView = dataPickerView
dataPickerView.delegate = self
dataPickerView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldDidBeginEditing(textField: UITextField) {
if textField == enterSeason {
activeDataArray = season
} else
if textField == enterSport {
activeDataArray = sport
}
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return activeDataArray.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return activeDataArray[row] as! String
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if activeDataArray == season {
enterSeason.text = season[row] as! String
}
else if activeDataArray == sport {
enterSport.text = sport[row] as! String
}
}
}
This is my first project and I am learning a lot from S.O. Thank you for all you patient responses.
Include
enterSport.inputView = dataPickerView
to set the correct firstResponder.
Set dataPickerView as enterSport's inputview
enterSport.inputView = dataPickerView;