Content in PickerView not showing up - ios

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
}

Related

how do I load the UIpicker on page load in swift?

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

Multiple pickerviews in single viewController

Is it possible to have a single pickerView in swift which changes its value based on the button pressed. I could not figure out a way to implement more than one parameter through pickerView in a single ViewController. An alternative solution like a dropdown menu is fine too. Example/functional code would be great if provided. This is for a quiz app which would take multiple parameters.
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet weak var pickerView: UIPickerView!
#IBOutlet weak var selectionBtn: UIButton!
let animals = ["Lion", "Dog", "Monkey", "Cat", "Bat"]
override func viewDidLoad() {
pickerView.isHidden = true
pickerView.delegate = self
pickerView.dataSource = self
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func selectPressed(_ sender: UIButton) {
if pickerView.isHidden {
pickerView.isHidden = false
}
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return animals.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return animals[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectionBtn.setTitle(animals[row], for: .normal)
pickerView.isHidden = true
}
}
Yes by having more than 1 data source
let animals1 = ["Lion", "Dog", "Monkey", "Cat", "Bat"]
let animals2 = ["Lion", "Dog", "Monkey", "Cat", "Bat"]
var mainData = [String]()
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return mainData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, fo rComponent component: Int) -> String? {
return mainData[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectionBtn.setTitle(mainData[row], for: .normal)
pickerView.isHidden = true
}
assign mainData to say animal1
and reload
pickerView.reloadAllComponents()
Keep a separate array and put your array into it according to your logic. Use that array in pickerview. Try This:
let animals = ["Lion", "Dog", "Monkey", "Cat", "Bat"]
let secondAnimals = ["Lion1", "Dog1", "Monkey1", "Cat1", "Bat1"]
let pickerArray = [String]()
#IBAction func selectPressed(_ sender: UIButton) {
pickerArray = animals //change it according to your logic
pickerView.reloadAllComponents()
pickerView.isHidden = !pickerView.isHidden
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerArray.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerArray[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectionBtn.setTitle(pickerArray[row], for: .normal)
pickerView.isHidden = true
}
You can have two arrays to populate the picker like this
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
if numb == 1
{
return firstArray.count
}
else
return secondArray.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if numb == 1
{
return firstArr[row]
}
else
{
return secondArr[row]
}
}
Whenever you have to change the data source for datepicker, make sure after that you are calling method
picker.reloadAllComponents()
Take flag and use appropriate data source.
let say you added 2 PickerView to your View
- set the 1st picker´s tag as 1 & 2 for the 2nd picker under the Attributes Inspector
- CTRL + drag from each picker to the top yellow View Controller icon and choose dataSource.Repeate the same choosing delegate
- repeate the above for the other picker too
- add pickerview & pickerviewdelegation to your ViewController class:
class ViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {
in your ViewController class, create empty arrays for the pickers:
var picker1Options = []
var picker2Options = []
on viewDidLoad() method, populate the arrays with your content:
picker1Options = ["p1 1","p1 2","p1 3","p1 4","p1 5"]
picker2Options = ["p2 1","p2 2","p2 3","p2 4","p2 5"]
implement the delegate & pickerview methods:
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if (pickerView.tag == 1){
return picker1Options.count
}else{
return picker2Options.count
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
if (pickerView.tag == 1){
return "\(picker1Options[row])"
}else{
return "\(picker2Options[row])"
}
}
Hope this will help.
let arrAny : [String] = [String]()
button action:
#IBAction func btn2Pressed(_ sender: UIButton) {
arrAny = ["Lion1", "Dog1", "Monkey1", "Cat1", "Bat1"]
if pickerView.isHidden {
pickerView.isHidden = false
}
}
#IBAction func btn1Pressed(_ sender: UIButton) {
arrAny = ["Lion", "Dog", "Monkey", "Cat", "Bat"]
if pickerView.isHidden {
pickerView.isHidden = false
}
}
pickerView delegate:
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return arrAny.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return arrAny[row]
}

Invalid redeclaration of 'numberOfComponents(in:)' error

Here's my code. I would say the steps I have taken, but they just don't make sense and I'd get made fun of, I am very new to Swift and Xcode. But how do I declare a group of components? I thought I spaced them enough, I have honestly searched for guides, but no one really focuses on dropdowns and variables within the dropdowns.
import UIKit
class SecondViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var backBTN: UIButton!
#IBOutlet weak var label: UILabel!
#IBOutlet weak var labelTwo: UILabel!
#IBOutlet weak var pickerView: UIPickerView!
#IBOutlet weak var pickerviewTwo: UIPickerView!
var pickerData = ["X", "Y"]
var pickerdataTwo = ["R","D","C"]
override func viewDidLoad() {
super.viewDidLoad()
pickerView.delegate = self
pickerView.dataSource = self
pickerviewTwo.delegate = self
pickerviewTwo.dataSource = self
}
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 {
return pickerData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerData[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
label.text = pickerData[row]
}
func numberOfComponents(in pickerviewTwo: UIPickerView) -> Int {
return 1
}
func pickerviewTwo(_ pickerviewTwo: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerdataTwo.count
}
func pickerviewTwo(_ pickerviewTwo: UIPickerView, titleForRow row: Int, forComponent
component: Int) -> String? {
return pickerdataTwo[row]
}
func pickerviewTwo(_ pickerviewTwo: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
labelTwo.text = pickerdataTwo[row]
}
}
Your picker view code is wrong. First, I would recommend changing the names of them from pickerView and pickerViewTwo to something more descriptive.
The required functions for picker view can't be used multiple times, thus you are getting the error. The proper way to do it is:
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent
component: Int) -> String? {
//After renaming the first pickerView to topPickerView
if pickerView == topPickerView {
return pickerData[row]
}
else {
return pickerDataTwo[row]
}
}
There should be an if-else in each of the required functions, with the if statement saying that if pickerView == oneOfThePickerViewsName, with the if else statement. Whats happening is when the pickers are being set up, it checks which picker it is and uses the code for that.
Here is how the rest should be formatted:
//pickerView has been renamed to topPickerView
func numberOfComponents(in pickerView: UIPickerView) -> Int {
//You wouldn't need to do this here as its the same for both of them.
//
if pickerView == topPickerView
{
return 1
}
else
{
return 1
}
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView == topPickerView
{
return pickerData.count
}
else
{
return pickerdataTwo.count
// should actually be formatted pickerDataTwo because of camelCase.
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent
component: Int) -> String? {
if pickerView == topPickerView
{
return pickerData[row]
}
else
{
return pickerdataTwo[row]
// should actually be formatted pickerDataTwo because of camelCase.
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent
component: Int) {
if pickerView == topPickerView
{
label.text = pickerData[row]
}
else
{
labelTwo.text = pickerdataTwo[row]
// should actually be formatted pickerDataTwo because of camelCase.
}
}

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

Type 'x' does not conform to protocol 'UIPickerViewDataSource'

import UIKit
class FourthViewController: UIViewController,UIPickerViewDelegate,UIPickerViewDataSource {
#IBOutlet weak var picker: UIPickerView!
var pickerData: [String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.picker.delegate = self
self.picker.dataSource = self
pickerData = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6"] }
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - Delegates and data sources
//MARK: Data Sources
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
//MARK: Delegates
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerData[row]
}
/*
// 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.
}
*/
}
Error:Type 'FourthViewController' does not conform to protocol
'UIPickerViewDataSource'
Just for testing some features but i dont get the problem
As you have found, you need to implement numberOfComponents(in:).
Your numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int, needs to be changed to:
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
Also you need to modify your pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?:
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerData[row]
}
In Swift 3 many methods are renamed. Check the latest reference, and be careful about this. And you better remark Xcode version in your question.
You must conform data source protocol:
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
Try this code:
//MARK: - Delegates and data sources
//MARK: Data Sources
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
//MARK: Delegate
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerData[row]
}
You have to implement all the required methods of UIPickerViewDataSource and UIPickerViewDelegate if you confirming that protocol in swift. otherwise it will give error at compile time.
I got error due to the delegate method
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
{
if pickerView == stylePickerView {
return 1 }
else if pickerView == fontPickerView {
return 1 }
return 0
}
tried this instead and worked
#available(iOS 2.0, *)
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
if pickerView == stylePickerView {
return 1 }
else if pickerView == fontPickerView {
return 1 }
return 0
}
You are missing this from the delegate:
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}

Resources