PickerView shows only '?' - ios

This is my source code and what I have done is make picker view on storyBoard. Make IBOutlet in this controller by contorl+drag.
It can be compiled however, only '?' appears in the picker view.
Where is the problem?
import UIKit
class SelectViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate{
var songNames = ["test1","test2","test3"]
#IBOutlet weak var songPicker: UIPickerView!
override func viewDidLoad(){
songPicker.delegate = self
songPicker.dataSource = self
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return songNames.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int) -> String? {
return songNames[row]
}
}

You have missed the forComponent parameter from the dataSource method. Add it in your titleForRow function like this:
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return songNames[row]
}
This should fix the problem you are having.

Related

Get selected value from picker view (picker wheel)

I'm currently using XCode version 11.3.1 (11C505) and Swift 5 and I can't seem to find a good answer as to how to get the selected value from a picker wheel (view). Here's the relevant code from my ViewController.swift
class ViewController: UIViewController {
#IBOutlet weak var numberPicker: UIPickerView!
#IBOutlet weak var test: UILabel!
private let possibleNums: [Int] = Array(1...16) // Create an array of Ints from 1 to 16
override func viewDidLoad() {
super.viewDidLoad()
numberPicker.dataSource = self
numberPicker.delegate = self
}
}
extension ViewController: UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return possibleNums.count
}
// Attempt at getting the selected value, didn't work
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int {
print(possibleNums[numberPicker.selectedRow(inComponent: 0)])
test.text = "\(possibleNums[numberPicker.selectedRow(inComponent: 0)])"
}
}
extension ViewController: UIPickerViewDelegate {
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return String(possibleNums[row])
}
}
Edit: Solution was also in comments so I figured I'd put it here in case anyone else finds this:
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int should be func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int (missing _)
and test.text = "\(possibleNums[numberPicker.selectedRow(inComponent: 0)])" should just be test.text = "\test.text = "\(possibleNums[row])"
Change test.text = "\(possibleNums[numberPicker.selectedRow(inComponent: 0)])" to this: test.text = "\(possibleNums[row])"
You only have one component, so you don't need to check for it, just return the row number as the array's index.
The easiest way to do that is to change your didSelectRow function from
test.text = "\(possibleNums[numberPicker.selectedRow(inComponent: 0)])"
to
test.text = "\(possibleNums[rows])"

Creating Second Delegate

I'm trying to create a second UIPickerView delegate so I can control them individually instead of using if blocks. Below is an example I put together, I'm unsure of how to connect the second UIPickerView outlet to the second UIPickerView delegate (assuming that is all I am missing).
import UIKit
protocol secondDelegate {
func secondPickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
func secondNumberOfComponents(in pickerView: UIPickerView) -> Int
}
protocol secondDelegateDataSource {
func secondPickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
}
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, secondDelegate, secondDelegateDataSource {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
p1.delegate = self
p1.dataSource = self
p2.delegate = self
p2.dataSource = self
}
#IBOutlet weak var p1: UIPickerView!
#IBOutlet weak var p2: UIPickerView!
var delegate2: secondDelegate?
var dataSource2: secondDelegateDataSource?
let picker1 = ["1","3","5"]
let picker2 = ["2","4","6"]
// first picker
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return picker1.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return picker1[row]
}
// second picker
func secondNumberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func secondPickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return picker2.count
}
func secondPickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return picker2[row]
}
}
So here's the problem: you are saying the words "second delegate", but in fact you still have just one delegate — the view controller.
That's your mistake. Make your deeds match your words. Get all the delegate code out of the view controller. Instead, give your view controller two helper objects — the two picker delegates. Route the dataSource and delegate properties of the two pickers correctly, one to each delegate. Now the messages are coming and going to completely separate places, and you will not have any single bottleneck with if clauses everywhere as you do now.
Here's a simplified example where the two helpers are instance of one class — naturally, nothing requires that you do it that way:
class Helper: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
let data: [String]
init(data: [String]) {
self.data = data
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
data.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
data[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
print(data[row])
}
}
class ViewController: UIViewController {
#IBOutlet weak var p1: UIPickerView!
#IBOutlet weak var p2: UIPickerView!
let helper1 = Helper(data:["Manny", "Moe", "Jack"])
let helper2 = Helper(data:["Harpo", "Chico", "Groucho"])
override func viewDidLoad() {
super.viewDidLoad()
p1.delegate = helper1
p1.dataSource = helper1
p2.delegate = helper2
p2.dataSource = helper2
}
}
If the two picker views do very different kinds of thing, then you would want two separate Helper classes, each of which acts as a picker view delegate in its own way. Again, the goal here is to avoid having to examine the pickerView in the datasource and delegate methods and decide with an if clause what to do; each Helper type would do just one thing.

UIPickerView accessiblityLabelForComponent not being called

I am trying to set accessibility label for UIPickerView component, but the delegate method is never called. What's more, UIInspector shows the pickerView is not accessible, but it has the label actually set.
The dataSource/delegate methods are fired. Only the UIAccessibilityDelegate is not.
Tested on xcode 10.1 iOS 12.1 simulator
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UIPickerViewAccessibilityDelegate {
#IBOutlet weak var pickerView: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
pickerView.isAccessibilityElement = true
pickerView.accessibilityLabel = "TESTAccLabel"
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return 5
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return "\(component) - \(row)"
}
func pickerView(_ pickerView: UIPickerView, accessibilityLabelForComponent component: Int) -> String? {
return "TODO:JS"
}
}

I can't add a UIPickerview for gender in a registration form

I am creating a registration form and I have to include the gender inside a text field using a picker view. However, I am getting question marks instead of male and female.
Here is my code:
#IBOutlet weak var genderfield: UITextField!
let pickerView = UIPickerView()
let gender1 = ["Male", "Female"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return gender1.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
func pickerView(_ pickerView:UIPickerView,didSelectRow row: Int,forComponent component: Int){
genderfield.text = gender1[row]
genderfield.resignFirstResponder()
}
And in ViewDidLoad:
pickerView.delegate = self
pickerView.dataSource = self
genderfield.inputView = pickerView
I don't think there is something wrong in my code. I have been googling for hours.
You get question marks because you have the wrong signature on your titleForRow delegate method.
Change:
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
to:
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
Note the addition of _ just after the (.
You can not added UIPickerViewDelegate, UIPickerViewDataSource.
so when you add delegate and data source of picker view its work fine.
like this:
extension RegisterVC : UIPickerViewDelegate, UIPickerViewDataSource{
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return gender1.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
func pickerView(_ pickerView:UIPickerView,didSelectRow row: Int,inComponent component: Int){
genderfield.text = gender1[row]
genderfield.resignFirstResponder()
}

UiPickerview values displayed as question mark ("?")in swift - But getting the correct value while assigning it to a textBox

//I am able to see the correct value in the text box upon scrolling down the picker view. But the picker view display is coming as "?" (question marks). I am confused with where I need to assign the pickerview as input view to the textbox . But still that won't make any sense to the error I am facing right .
I am using Xcode 9 and Swift 3.2.
class BillDetailsViewController: UIViewController ,UITextFieldDelegate,UIPickerViewDelegate,UIPickerViewDataSource{
//Variables Declaration
//Picker view outlet
#IBOutlet var datePickerView: UIPickerView!
//Picker view datasource - integer array
var integerArray = [Int](1899...2500)
//Textbox where picked value to be shown
#IBOutlet var txtPaidYear: UITextField!
//ViewLoad
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
datePickerView.isHidden = true
datePickerView.reloadAllComponents()
datePickerView.dataSource = self
datePickerView.delegate = self
txtPaidYear.inputView = datePickerView
}
//picker view delegate functions
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return integerArray.count
}
public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
let pickerValue: String = String(integerArray[row])
return pickerValue
}
public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
txtPaidYear.text = String(integerArray[row])
self.datePickerView.reloadAllComponents()
}
}
****You have to change method like this after that it will work definitely.**
and Delete Delegate for TextField which you are using..**
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
}
I just removed all the TextView delgates in the class and it worked . Still need to figure out what was the exact issue . One of the textView delegate method was causing the issue it seems . I need to figure it out.Anyway issue got fixed .I just created an independent project and implemented UIPIckerView for which it was working perfect. Hence I did the same in my project removing all the textview delegate methods .
Thanks much for all your support .
Replace:
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int) -> String? {}
With:
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {}

Resources