Problem With Multiple PickerViews in one View Controller - ios

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!

Related

Content in PickerView not showing up

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
}

PickerView data not proper on using multiple pickerview

I am using multiple pickerview on one viewcontroller. I am getting correct data in the respective pickerviews but the view of rows symmetry in the pickerview is not correct. The data view in 1st pickerview is correct but in the second pickerview the rows start from the bottom of the pickerview.
I have attached screenshots of both pickerviews.
1st pickerview
2nd pickerview
For distinguishing between the 2 pickers, I have used pickerview tags.
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView.tag == 31{
return arr_statename.count
}else{
return arr_cityname.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView.tag == 31{
return arr_statename[row]
}else{
return arr_cityname[row]
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView.tag == 31{
state.text = arr_statename[row]
}else{
city.text = arr_cityname[row]
}
}
Can anyone please help? Thanks.
Try this i hope might be helpful!!
Just add the observer in view did load
NSNotificationCenter.defaultCenter().addObserver(self, selector:#selector(self.updatePicker), name: UITextFieldTextDidBeginEditingNotification, object: nil)
and Reload the components
func updatePicker(){
self.pickerView.reloadAllComponents()
}
Have you considered using a single pickerView with 2 components instead of two separate pickerViews on the same viewController? If it fulfills the needs of your app, using a single multi-component pickerView provides a better UI and avoids the types of problems you are experiencing.

Using Two UI Pickers in 1 VC, Handling Delegate methods

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 {
...
}
}

Why isn't UIPickerView showing rows? swift

I'm trying to make a single UIPickerView with 2 components, each with a different amount of rows. I thought that I could base the row number per component on the index of the component, but when I run my app the UIPickerView displays only one single blank row and doesn't allow scrolling.
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 2
}
// grades is a 2D array
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return grades[component].count
}
// level and letter are predefined ints
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
level = row
}else if component == 1 {
letter = row
}
return ""
}
EDIT:
This is my viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
pickerView.dataSource = self;
pickerView.delegate = self;
}
I believe you should return non-empty title to make it work
...
// level and letter are predefined ints
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
level = row
} else if component == 1 {
letter = row
}
return "Component: \(component) Row: \(row)" // whatever string you want to display
}

How can I populate a picker view depending on the selection of another picker view in Swift?

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
}

Resources