I have 2 pickers in 1 VC and know that this should be handled by using if else to identify which delegate methods each should follow. However Im new to getting my head around this and im not sure what i should be returning on my methods in order to have them work correctly.
Here is the code, I have just used 0 and "" to prevent code errors for now until I can get the correct returns sorted out.
func numberOfComponents(in pickerView: UIPickerView) -> Int {
if pickerView == repsPicker {
return 1
} else if pickerView == setsPicker {
return 1
}
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == repsPicker {
return repPickerValues.count
} else if pickerView == setsPicker {
return self.setsPickerValues.count
}
return 0
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == repsPicker {
return repPickerValues[row]
} else if pickerView == setsPicker {
return self.setsPickerValues[row]
}
return ""
}
You can set tag to each picker so that you can differentiate between them. Set pickerView.tag with two different values, and in each delegate method check the tag value to determine the return value.
let repPickerValues = ["America", "Mexico", "Canada"]
let setsPickerValues = ["India", "China", "Malaysia", "Singapore"]
If these are your values, then you will have 3 options on 1st picker and 4 options on 2nd picker.
Adding below lines will call those functions
repsPicker.delegate = self
setsPicker.delegate = self
And your view controller class should conform to UIPickerViewDelegate and UIPickerViewDataSource. Like
class ViewController: UIPickerViewDelegate, UIPickerViewDatSource {
}
This function will tell picker view how many options are to be shown
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == repsPicker {
return repPickerValues.count
} else if pickerView == setsPicker {
return self.setsPickerValues.count
}
return 0
}
This function is responsible for placing values in picker view
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == repsPicker {
return repPickerValues[row]
} else if pickerView == setsPicker {
return self.setsPickerValues[row]
}
return ""
}
Is this what you are asking for?
I can see several options here :
Use different delegate objects for each picker
picker1.delegate = firstDelegate()
picker2.delegate = secondDelegate()
Implement the desired delegate methods differently in each of the delegate objects.
Keep a reference to each picker in your view controller (or IBOutlet)
let picker1 = ...
let picker2 = ...
Then in your delegate method(s)
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == picker1 {
...
}
}
Related
What would be the best way to get the value from a PickerView without having a datasource? So i can not read values from i.e. an array.
Current values are just row numbers, that i need to read after user is done with picking.
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return 300
} else {
return 10
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return "\(row)."
} else {
return "\(row)"
}
}
You can use pickerView.selectedRow(inComponent:)
let firstValue = pickerView.selectedRow(inComponent: 0)
let secondValue = pickerView.selectedRow(inComponent: 1)
Both will just be an Int value representing the currently selected row index in it's respective component. And since your values are starting from 0, you can use the values directly.
You simply add this func:
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
print(row)
}
Just take care that row starets at 0
I have two pickers and I want picker1 to be show by default when the page first loads and also when user touches the UI. I want to show in both ways for picker1.
func numberOfComponents(in pickerView: UIPickerView) -> Int {
if pickerView == picker1 {
return 1
} else {
return 2
}
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
var tempCount = 0
if pickerView == picker1 {
tempCount = pickerData.count
} else {
}
return tempCount
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
var tempPickerData = ""
if pickerView == picker1 {
tempPickerData = pickerData[row]
} else {
}
return tempPickerData
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == picker1 {
selected = pickerData[row]
} else {
}
}
So I am getting this strange problem as I try to use multiple PickerViews in one view controller. I have set it up so that I use an if / else if so that it checks which picker to put the correct data to. I have 3 pickers total, and the first two work fine, but the third one never shows any data. Here are the functions:
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == sitePicker {
return sitePickerData.count
} else if pickerView == sizePicker {
return sizePickerData.count
} else if pickerView == profilePicker {
return profilePickerData.count
} else {
return 0
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == sitePicker {
return "\(sitePickerData[row])"
} else if pickerView == sizePicker {
return "\(sizePickerData[row])"
} else if pickerView == profilePicker {
return "\(profilePickerData[row])"
}
return ""
}
}
the sitePickerData, sizePickerData, etc are string arrays which hold the options to scroll through on the picker. Once again, the first two work fine, but the third picker does not show any data from the array. Any help is appreciated, thanks!
I am new with programming in Swift. i got problem when i want to show up 2 different picker with 2 different content. But it show (?) instead of content.
see the screenshoot below
Thank your for help!
let fruit = ["apple", "orange", "watermelon", "banana", "peach", "strawberry"]
let food = ["rice","bread","spagheti","milk"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if (pickerView.tag == 1) {
return fruit.count
}
else {
return food.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if (pickerView.tag == 1) {
return fruit[row]
}
else {
return food[row]
}
}
First of all check you pickerView DataSource and Delegate connected properly and then you can conditionally load data by comparing pickerView like below.
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == YOUR_FIRST_PICKER {
return fruit.count
}
else {
return food.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView == YOUR_FIRST_PICKER {
return fruit[row]
}
else {
return food[row]
}
}
I think you haven’t set your pickers’ delegates and data sources.
First add these protocols to your ViewController subclass
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource
then in viewDidLoad set delegates and data sources of your pickers as self
override func viewDidLoad() {
super.viewDidLoad()
pickerView1.delegate = self
pickerView1.dataSource = self
pickerView2.delegate = self
pickerView2.dataSource = self
}
Looking for a solution to populate a picker view depending on the selection of another picker view within the same view controller.
The first selects a category. The second the items of that category.
Here's what I (Swift beginner) came up with:
import UIKit
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
var countryClasses = ["US", "EU", "JP"]
var usItems = ["usitem1", "usitem2", "usitem3", "usitem4", "usitem5"]
var euItems = ["euitem1", "euitem2", "euitem3", "euitem4", "euitem5"]
var jpItems = ["jpitem1", "jpitem2", "jpitem3", "jpitem4", "jpitem5"]
#IBOutlet weak var countryPicker: UIPickerView!
#IBOutlet weak var itemPicker: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
self.countryPicker.dataSource = self;
self.countryPicker.delegate = self;
self.itemPicker.dataSource = self;
self.itemPicker.delegate = self;
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return countryClasses.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return countryClasses[row]
}
}
As both the Pickers are using the same delegate you are going to need a way to identify them when your delegate methods run, also your current Array structure means you are going to need a way to select each item array as and when the country is selected.
Create a store for the selected item array.
var selectedItemsArray = []
Add some checks to your delegate methods.
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == countryPicker {
return countryClasses.count
} else if pickerView == itemPicker {
return selectedItemsArray.count
}
return 0
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
if pickerView == countryPicker {
return countryClasses[row]
} else if pickerView == itemPicker {
return selectedItemsArray[row]
}
return 0
}
Then you need to implement did Select row to setup the item store and reload the data.
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == countryPicker {
switch row {
case 0:
selectedItemsArray = usItems
case 1:
selectedItemsArray = euItems
case 2:
selectedItemsArray = jpItems
default:
selectedItemsArray = []
}
// IMPORTANT reload the data on the item picker
itemPicker.reloadAllComponents()
} else if pickerView == itemPicker {
// Get the current item
var item = selectedItemsArray[row]
// Assign value to a label based on which array we are using
if selectedItemsArray == usItems {
usLabel.text = item
} else if selectedItemsArray == euItems {
euLabel.text = item
} else if selectedItemsArray == jpItems {
jpLabel.text = item
}
}
}
I haven't tested this code, but the logic should be correct.
Associate each picker view with a TAG (so that they can be identified) then in picker delegate identify these pickers on basis of these identiers and show other one
Thanks #Wez!
In Swift 2.2, small but important correction return the function as String makes it works great.
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
if pickerView == countryPicker {
return countryClasses[row]
} else if pickerView == itemPicker {
return selectedItemsArray[row]
}
return selectedItemsArray[row] as? String
}