I am trying to add a pickerview to my iphone application but instead of showing string from my array it shows question marks. Does anyone know why? I've been trying to figure it out for the past hour... Here is my code of the controller that contains the pickerview:
class NewIssueViewController: UIViewController, UIPickerViewDelegate {
var componentArr = ["component1","component2","component3","component4"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func CancelPressed(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func AddPressed(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
func numberOfComponentsInPickerView(pickerView: UIPickerView!) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView!, numberOfRowsInComponent component: Int) -> Int {
return componentArr.count
}
func pickerView(pickerView: UIPickerView!, titleForRow row: Int, forComponent component: Int) -> String! {
return componentArr[row]
}
}
You set your picker view's datasource, but didn't set its delegate.
As a result pickerView:titleForRow: never gets called.
You should either connect the PickerView's Datasource and Delegate in the storyboard or set them programatically. See the image below.
New Swift 3 has deprecated usage of above methods,
i have implemented the following to make them work. (Some underscore added in param.
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerDataSource.count;
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerDataSource[row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
/*if(row == 0)
{
self.view.backgroundColor = UIColor.whiteColor();
}
else if(row == 1)
{
self.view.backgroundColor = UIColor.redColor();
}
else if(row == 2)
{
self.view.backgroundColor = UIColor.greenColor();
}
else
{
self.view.backgroundColor = UIColor.blueColor();
}*/
}
Just add self.pickerOutletReference.delegate = self on viewDidLoad() menthod
Related
I have a UIPickerView that when tapping the done button, keeps selecting the last option of the Array. I can tap on either the UITextField or a button I'm using that assigns the UITextField as the first responder. My code is as follows:
Edit. I should also mention that I'm using Xcode 11 GM Seed if that was to make a difference. I tested a clean version of the code shown below on a separate project with nothing else and it is displaying the same behavior.
#IBOutlet weak var sortTypeTextField: UITextField!
var selectedSortOption = String()
let sortOptions = [
USER_REVIEWS_SORT_OPTION_DATE,
USER_REVIEWS_SORT_OPTION_LIKES,
USER_REVIEWS_SORT_OPTION_DISLIKES
]
sortOptions above is an array of Strings located in a different file but for the purpose of this question I’ll add here:
let USER_REVIEWS_SORT_OPTION_DATE = "Date"
let USER_REVIEWS_SORT_OPTION_LIKES = "Number of Likes"
let USER_REVIEWS_SORT_OPTION_DISLIKES = "Number of Dislikes"
let DONE_TOOLBAR_BUTTON_TITLE = "Done"
I have a function setupUI which I call in viewDidLoad along with the value for the sortTypeTextField. The value is the first String in the array when the viewController first loads.
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
func setupUI() {
sortTypeTextField.text = sortOptions[0]
createSortPicker()
createPickerToolbar()
}
func createSortPicker() {
let sortPicker = UIPickerView()
sortPicker.delegate = self
sortTypeTextField.inputView = sortPicker
}
func createPickerToolbar() {
let toolBar = UIToolbar()
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: DONE_TOOLBAR_BUTTON_TITLE, style: .plain, target: self, action: #selector(dismissKeyboard))
toolBar.setItems([doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
sortTypeTextField.inputAccessoryView = toolBar
}
#objc override func dismissKeyboard() {
view.endEditing(true)
}
I’m also using a button to display the UIPicker as shown here:
#IBAction func sortRatingsButtonWasTapped(_ sender: Any) {
sortTypeTextField?.becomeFirstResponder()
}
As shown below, I want for the sortTypeTextField value to change to the selected option but for some reason when tapping the Done button in the toolbar, the text shown is always the third String in the array regardless if I have chosen the first, the second or the third.
extension ReviewsViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
sortOptions.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return sortOptions[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedSortOption = sortOptions[row]
sortTypeTextField.text = selectedSortOption
}
}
It seems to be a bug in the simulator. I tested the my code above and the code provided by Abdul Karim Khan on my device and the work as they should. The label updates according to the option selected in the picker view.
This is how I created pickerView,
class ViewController: UIViewController {
#IBOutlet weak var selectaday: UITextField!
let days = ["monday","wednesday"]
var selectedDay: String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
createDayPicker()
}
func createDayPicker(){
let dayPicker = UIPickerView()
dayPicker.delegate = self
selectaday.inputView = dayPicker
}
}
extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource{
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return days.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return days[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedDay = days[row]
selectaday.text = selectedDay
}
}
I am building a simple app that has a PickerView with 3 selections that should link to 3 viewControllers each named FirstViewController, SecondViewController and ThirdViewController.
But I am getting this error
> NSInvalidArgumentException', reason: 'Receiver (<Scroller.ViewController: 0x7ff7b5e0b670>) has no segue with identifier 'SecondSegue'
I have three options in the picker and a button to go to that selection's viewController:
My code below works on first loading then crashes
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBAction func continueButtonPressed(_ sender: AnyObject) {
self.performSegue(withIdentifier: "\(chosenState)Segue", sender: nil)
print("no chance")
}
#IBOutlet weak var pickerView: UIPickerView!
var pickerData = ["First","Second","Third"]
var chosenState = ""
override func viewDidLoad() {
super.viewDidLoad()
print("Help")
pickerView.delegate = self
pickerView.dataSource = self
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// The number of columns of data
// The number of rows of data
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
// The data to return for the row and component (column) that's being passed in
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerData[row]
}
//Called when the user changes the selection...
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
chosenState = pickerData[row]
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
}
can anyone help me understand how to fix this ?
Have I named the Segues ok? They are all named the same - is that correct?
You have to set the segue identifier to second view controller as SecondSegue
It seems your SecondSegue to your second UIViewController has not been named properly.
Be careful, it is case sensitive, it must be named precisely SecondSegue. And after having changed the name, don't forget to validate your input with the return key.
I was searching very much, but i did not find an answer for my question.
My app should change the data of one picker after the other picker was changed.
As you can see, in the titleForRow method, I want to set the data and I also know that this method is just called once, but I just do not know where and also how I should do it then.
I think, on the didSelectRow method I could set the data, too, but there I do not have a gleam how I should do it.
Here is my code, I hope this is helpful.
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
var x = 0
#IBOutlet weak var leaguePicker: UIPickerView!
#IBOutlet weak var clubPicker: UIPickerView!
let league = ["Bundesliga", "Premier League"]
let club = [["ManCity", "Arsenal"],["Bayern", "Dortmund"]]
override func viewDidLoad() {
super.viewDidLoad()
leaguePicker.delegate = self
leaguePicker.dataSource = self
clubPicker.delegate = self
clubPicker.dataSource = self
}
func numberOfComponents(in picker: UIPickerView) -> Int {
return 1
}
func pickerView(_ picker: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{
switch (picker){
case leaguePicker:
return league.count
case clubPicker:
return club.count
default:
return 1
}
}
func pickerView(_ picker: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch (picker){
case leaguePicker:
return league[row]
case clubPicker:
if (x==0){
print("titleForRow call.. x=0")
return club[0][row]
// this is just happening at the beginning
} else {
print("titleForRow call.. x=1")
return club[1][row]
// this does not happen
}
default: return "an error occurred"
}
}
func pickerView(_ picker: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
if (picker == leaguePicker) {
if (row==0){
//clubPicker.selectRow(0, inComponent: 0, animated: true)
x=0
} else {
x=1 // this call is working
//clubPicker.selectRow(0, inComponent: 1, animated: true)
}
}
picker.reloadAllComponents()
//this does not lead to call titleForRow
}
}
You need to reload the 2nd picker when the value in the 1st picker changes.
func pickerView(_ picker: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
if (picker == leaguePicker) {
x = row
clubPicker.reloadAllComponents()
}
}
You also need to fix the numberOfRowsInComponent:
func pickerView(_ picker: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{
switch (picker){
case leaguePicker:
return league.count
case clubPicker:
return club[x].count
default:
return 1
}
}
And your titleForRow can be simplified:
func pickerView(_ picker: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch (picker){
case leaguePicker:
return league[row]
case clubPicker:
return club[x][row]
default: return "an error occurred"
}
}
I also suggest you renamed your x variable to something more useful such as selectedLeague.
I'm trying to make items show up on my pickerView, I can't seem to figure out why its not showing up. Any Suggestions?
import UIKit
class InspectionViewController: 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.
// Connect data:
self.picker.delegate = self;
self.picker.dataSource = self;
// Input data into the Array:
pickerData = ["53W4", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6"];
}
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]
}
/*
// 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.
}
*/
}
You should use this:
func pickerView(
_ pickerView: UIPickerView,
titleForRow row: Int,
forComponent component: Int
) -> String? {
pickerData[row]
}
instead of:
func pickerView(
pickerView: UIPickerView,
titleForRow row: Int,
forComponent component: Int
) -> String! {
pickerData[row]
}
The diff is in Omitting Argument Labels.
Here is a doc link
I can't figure out why I can't access this variable, see below, I want the value of sport result when it's clicked, however sportResult.selectedSport returns nil?
let sportPickerData = SportPickerData()
override func viewDidLoad() {
super.viewDidLoad()
sportPickerView.delegate = sportPickerData
sportPickerView.dataSource = sportPickerData
class SportPickerData: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
var sports = ["Football", "Baseball", "Hockey", "Basketball"]
var selectedSport: String?
func numberOfComponentsInPickerView(yearPicker: UIPickerView) -> Int {
return 1
}
func pickerView(yearPicker: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return sports.count
}
func pickerView(yearPicker: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedSport = sports[row]
}
func pickerView(yearPicker: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return "\(sports[row])"
}
}
let sportResult = SportPickerData()
#IBAction func button(sender: UIButton) {
label.text = sportResult.selectedSport
}
sportResult its not a delegate or a data source of your picker view so its selectedSport property will never be initialized since its didSelectRow method will be never called. To get the selectedSport you have to get it from sportPickerData which is actually the delegate and data source of your picker
let sportResult = SportPickerData() // delete this line
#IBAction func button(sender: UIButton) {
label.text = sportPickerData.selectedSport
}