How to use multiple UIPickerViews in one view controller - swift

I am trying to set up 2 UIPickerViews in 1 view controller. I have not been able to find resources that solve my problem.
I have tried following the answer from Diavel Rider on How to use 2 UIPickerView's in one View Controller?. I got some errors from that. I have also tried adding tags but was not able to successfully do that. I am using Swift 4.
Here is the code of my view controller:
import UIKit
class FirstViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ foodTypeUIPickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
var countrows : Int = nutritionPickerData.count
if pickerView == foodTypeUIPickerView { **[Error Here: "Binary operator '==' cannot be applied to operands of type '_' and 'UIPickerView'"]**
countrows = self.foodTypePickerData.count
}
return countrows
}
func pickerView(_ foodTypeUIPickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == nutritionUIPickerView { **[Error Here: "Binary operator '==' cannot be applied to operands of type '_' and 'UIPickerView'"]**
let titleRow = nutritionPickerData[row]
return titleRow
} else if pickerView == foodTypeUIPickerView { **[Error Here: "Binary operator '==' cannot be applied to operands of type '_' and 'UIPickerView'"]**
let titleRow = foodTypePickerData[row]
return titleRow
}
return ""
}
#IBOutlet weak var nutritionUIPickerView: UIPickerView!
#IBOutlet weak var foodTypeUIPickerView: UIPickerView!
var nutritionPickerData = ["Protein", "Fiber", "Iron", "Fat", "Sodium", "Calcium/Vitamin D", "Energy", "Carbohydrates", "Cholestorol"]
var foodTypePickerData = ["Fruits", "Vegetables", "Legumes and Beans", "Grain", "Meat", "Dairy"]
#IBAction func submitUIButton(_ sender: Any) {
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.nutritionUIPickerView.delegate = self
self.nutritionUIPickerView.dataSource = self
self.foodTypeUIPickerView.delegate = self
self.foodTypeUIPickerView.dataSource = self
}
}
I need to use 2 picker views in 1 view controller. How do I do this?

You are referencing a non-existent variable named pickerView. You should update the parameter name to pickerView to avoid issues.
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == foodTypeUIPickerView {
return self.foodTypePickerData.count
} else {
return self. nutritionPickerData.count
}
}
Make a similar change to the other delegate/data source methods.

You should separate your data sources and delegates and not put them inside your view controller. Set those as the delegate and datasource. Code written in swift 4.2 xcode 10.1
class ViewController: UIViewController {
#IBOutlet weak var foodPicker: UIPickerView!
#IBOutlet weak var nutritionPicker: UIPickerView!
var foodData = FoodData()
var nutritionData = NutritionData()
override func viewDidLoad() {
super.viewDidLoad()
foodPicker.delegate = foodData
foodPicker.dataSource = foodData
nutritionPicker.delegate = nutritionData
nutritionPicker.dataSource = nutritionData
}
#IBAction func actionButton(_ sender: UIButton) {
let food = foodPicker.delegate?.pickerView!(foodPicker, titleForRow: foodPicker.selectedRow(inComponent: 0), forComponent: 0)
let nutrition = nutritionPicker.delegate?.pickerView!(nutritionPicker, titleForRow: nutritionPicker.selectedRow(inComponent: 0), forComponent: 0)
print("You picked: \(food) and \(nutrition)")
}
}
class FoodData: NSObject, UIPickerViewDelegate, UIPickerViewDataSource {
var foodTypePickerData = ["Fruits", "Vegetables", "Legumes and Beans", "Grain", "Meat", "Dairy"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return foodTypePickerData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return foodTypePickerData[row]
}
}
class NutritionData: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
var nutritionPickerData = ["Protein", "Fiber", "Iron", "Fat", "Sodium", "Calcium/Vitamin D", "Energy", "Carbohydrates", "Cholestorol"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return nutritionPickerData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return nutritionPickerData[row]
}
}

Related

multiple pickerview didSelectRow error in Swift

I have 2 pickerviews, 1 pickerview is to select a crypto-currency from an Array and the other pickerview is used to select a currency from an array. The problem I am having is when I run the app on simulator and select the cryptocurreny in cryptoPicker the app it also selects the same array value from currencyPicker and vice a versa. I don't want the array value of 0 to be pulled from both arrays unless it is selected by the user.
#IBOutlet weak var cryptoCurrentRate: UILabel!
#IBOutlet weak var currencyLabel: UILabel!
#IBOutlet weak var currencyPicker: UIPickerView!
#IBOutlet weak var cryptoPicker: UIPickerView!
#IBOutlet weak var cryptoLabel: UILabel!
var coinManager = CoinManager()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
coinManager.delegate = self
currencyPicker.dataSource = self
currencyPicker.delegate = self
cryptoPicker.dataSource = self
cryptoPicker.delegate = self
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == currencyPicker {
return coinManager.currencyArray.count
}
if pickerView == cryptoPicker {
return coinManager.cryptoArray.count
}
return 0
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == currencyPicker {
return coinManager.currencyArray[row]
}
if pickerView == cryptoPicker {
return coinManager.cryptoArray[row]
}
return ""
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let selectedCurrency = coinManager.currencyArray[row]
let selectedCrypto = coinManager.cryptoArray[row]
coinManager.fetchCryptoCoin(assetIdBase: selectedCrypto, assetIdQuote: selectedCurrency)
}
}
Do the same check for picker and in 'didSelectRow', you can do it like this:
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
var selectedCurrency: CurrencyModel? = nil
var selectedCrypt: CryptModel? = nil
if pickerView == currencyPicker {
selectedCurrency = coinManager.currencyArray[row]
}
if pickerView == cryptoPicker {
selectedCrypto = coinManager.cryptoArray[row]
}
coinManager.fetchCryptoCoin(assetIdBase: selectedCrypt == nil ? coinManager.cryptoArray[.zero] : selectedCrypt!, assetIdQuote: selectedCurrency == nil ? coinManager.currencyArray[.zero] : selectedCurrency!)
}
By default it will get the first value from 'coinManager.currencyArray' or 'coinManager.cryptoArray'

How to get the value that the user chose from a UIPickerView?

This is what I'm trying to accomplish:
I want to take the value that the user selected from 2 different pickerViews and display that value in a textField
let drivingGear = ["1", "12", "36", "60", "84"]
let boxVal = chooseDrivingGear
let boxVal2 = chooseDrivenGear1
let newVal = boxVal / boxVal2
resultBox1.text = newVal
However I couldnt get that to work so I'm now trying this:
#IBAction func chooseBox1Pressed(_sender: UIButton) {
sender.isHidden = true
if chooseDrivingGear.isHidden {
chooseDrivingGear.isHidden = false
}
if chooseDrivingGear[row] == "1" {
let v1 = 1
}
but chooseDrivingGear[row] shows this error: use of unresolved identifier 'row'
(My other code for pickerview) UPDATE:
//first picker view
chooseDrivingGear.isHidden = true
chooseDrivingGear.delegate = self
chooseDrivingGear.dataSource = self
chooseDrivingGear.tag = 0
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView.tag == 0 {
chooseBox1.setTitle(drivingGear[row], for: .normal)
chooseDrivingGear.isHidden = true
chooseBox1.isHidden = false
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return drivingGear[row]
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return drivingGear.count
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
chooseDrivingGear.isHidden = false
chooseDrivingGear2.isHidden = false
chooseDrivingGear3.isHidden = false
chooseDrivenGear1.isHidden = false
chooseDrivenGear2.isHidden = false
chooseDrivenGear3.isHidden = false
return false
}
You can simply try getting the selectedRow from both the pickerViews, get the values for the selected rows and the perform calculation on the values as required to show in the textField.
I have provided a sample code for that below.
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate
{
#IBOutlet weak var pickerView1: UIPickerView!
#IBOutlet weak var pickerView2: UIPickerView!
#IBOutlet weak var textField: UITextField!
let drivingGear = ["1", "12", "36", "60", "84"]
override func viewDidLoad()
{
super.viewDidLoad()
}
#IBAction func showResult(_ sender: UIButton)
{
let val1 = self.drivingGear[self.pickerView1.selectedRow(inComponent: 0)]
let val2 = self.drivingGear[self.pickerView2.selectedRow(inComponent: 0)]
if let intVal1 = Int(val1), let intVal2 = Int(val2)
{
let result = intVal1 / intVal2
self.textField.text = String(result)
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int
{
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{
return self.drivingGear.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{
return self.drivingGear[row]
}
}
Let me know if you still face any issues.

making a drop-down list in Swift 3

I'm trying to make drop-down list where picker view is not visible until user clicks on textfield. Then picker view disappears after user makes selection from pickerView. Currently, the picker View does not show up at all when I click on textfield.
import UIKit
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet weak var textBox: UITextField!
#IBOutlet weak var pickerView: UIPickerView!
var choices = ["SortBy:", "Date(ascending)", "Date(descending)","Calories Burned(descending)","Duration(descending)"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
self.view.endEditing(true)
return choices[row]
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return choices.count
}
fun pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.textBox.text = self.choices[row]
self.pickerView.isHidden = true
print("hello")
}
func textFieldDidBeginEditing(TextField: UITextField){
if TextField == self.textBox {
self.pickerView.isHidden = false
TextField.endEditing(true)
}
}
override func viewDidLoad() {
self.pickerView.isHidden = true
super.viewDidLoad()
}
}
try this :
override func viewDidLoad() {
self.pickerView.isHidden = true
super.viewDidLoad()
self.textBox.delegate = self
self.pickerView.delegate = self
}

How do I setup a second component with a UIPickerView

I've found some similar questions to this but none of the solutions matched my situation, and most were in objective-c which I don't know.
I'm trying to create a timer with minutes and seconds but I can't figure out how to wire up my second component.
How do I set up a second component with a UIPickerView?
This is what I have so far:
TimeViewController.swift
class TimeViewController: UIViewController, UIPickerViewDelegate {
#IBOutlet weak var timeSegueLabel: UILabel!
let minutes = Array(0...9)
let seconds = Array(0...59)
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return minutes.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return String(minutes[row])
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Thanks to #Bluehound for pointing me in the right direction. I had to look at some objective-c on GitHub to find out exactly how to do it, this is the answer I was looking for:
TimeViewController:
class TimeViewController: UIViewController, UIPickerViewDelegate {
#IBOutlet weak var timeSegueLabel: UILabel!
let minutes = Array(0...9)
let seconds = Array(0...59)
var recievedString: String = ""
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
//row = [repeatPickerView selectedRowInComponent:0];
var row = pickerView.selectedRowInComponent(0)
println("this is the pickerView\(row)")
if component == 0 {
return minutes.count
}
else {
return seconds.count
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
if component == 0 {
return String(minutes[row])
} else {
return String(seconds[row])
}
}
override func viewDidLoad() {
super.viewDidLoad()
timeSegueLabel.text = recievedString
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
This is the result:
Can do Picker with 2 components displaying in two labels
swift 4 xcode 9
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var lbl1: UILabel!
#IBOutlet weak var lbl2: UILabel!
#IBOutlet weak var picker1: UIPickerView!
var country = ["UK","US","JAPAN","UAE","CHINA","CANADA","EUROPE","IRAN","INDIA","ITALY" ]
var capital = [ "LONDON","WASHIGTON DC","TOKYO","ABU DHABI","BEIJING","OTTAWA","BRUSSELS","TEHRAN","NEW DELHI","ROME" ]
var val = 0
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return country.count
} else {
return capital.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return String(country[row])
} else {
return String(capital[row])
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
lbl1.text = country[row]
} else {
lbl2.text = capital[row]
}
}
}

How to connect UIPickerView + Button + call dictionary to display in label

I have a label, a picker (years), and a button. I want to be able to select the year on the picker, hit the button, and then display data associated with the year (a dictionary). Here's my code so far
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var picker: UIPickerView!
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent
component: Int) -> Int {
return years.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int,
forComponent component: Int) -> String! {
return years[row]
}
/* func pickerView(pickerView: UIPickerView!, didSelectRow row: Int,
inComponent component: Int) {
label.text = "\(years[row])"
}
*/
#IBAction func button(sender: UIButton) {
label.text =
}
here is my Model:
let years = ["2015", "2014", "2013", "2012"]
let winners = [
2015: "Patriots",
2014: "Seahawks",
2013: "Ravens",
2012: "Giants"
]
You need to do a few things to make this work. First, make your viewController conform to the UIPickerViewDataSource and UIPickerViewDelegate and set your picker's data source and delegate in viewDidLoad. Then you'll want to use the delegate method pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) to respond to changes to the pickerView. Store the selection in an instance variable and you should be good to go:
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var picker: UIPickerView!
let years = [2015, 2014, 2013, 2012]
let winners = [
2015: "Patriots",
2014: "Seahawks",
2013: "Ravens",
2012: "Giants"
]
var selectedYear: Int?
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
picker.dataSource = self
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return years.count
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedYear = years[row]
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return "\(years[row])"
}
#IBAction func button(sender: UIButton) {
if let year = selectedYear {
if let winner = winners[year] {
label.text = winner
}
}
}
}