Not able to save selected value from a UIPickerView to an array - ios

So far I have tried to use
func pickerView1(_ helpTypePicker: UIPickerView, didSelectRow row: Int, inComponent component: Int {
infoListInit.requestInfoList[4] = (helpTypePickerValues[row])
}
But the value is just not saving to the array. I tried printing the value after saving it, but to no avail. I do have helpTypePicker as a self delegate in my viewDidLoad func, so I don't know where to go from here. Other text values from UITextFields save fine, but none of my UIPickerViews are working in this regard
Here is the full class:
import Foundation
import UIKit
class requestHelpTypePickerScreen: UIViewController,
UIPickerViewDataSource, UIPickerViewDelegate {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent
component: Int) -> Int {
if pickerView.tag == 1 {
return helpTypePickerValues.count
} else {
return languagePickerValues.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView.tag == 1 {
return "\(helpTypePickerValues[row])"
} else {
return "\(languagePickerValues[row])"
}
}
// Mark: outlets
#IBOutlet weak var helpTypePicker: UIPickerView!
#IBOutlet weak var languagePicker: UIPickerView!
#IBOutlet weak var helpTypePickerLabel: UILabel!
let helpTypePickerValues = ["Academic/Professional", "Donate", "Food/Groceries", "Medication", "Emotional Support", "Misc."]
let languagePickerValues = ["Arabic", "Chinese", "Spanish", "English", "French", "Hindi/Urdu", "Korean", "Russian"]
override func viewDidLoad() {
super.viewDidLoad()
helpTypePicker.delegate = self
languagePicker.delegate = self
self.helpTypePicker.selectRow(2, inComponent: 0, animated: true)
self.languagePicker.selectRow(3, inComponent: 0, animated: true)
}
// Mark: actions
#IBAction func buttonPressed(_ sender: Any) {
func pickerView(_ helpTypePicker: UIPickerView,
didSelectRow row: Int,
inComponent component: Int) {
infoListInit.requestInfoList[5] = (helpTypePickerValues[row])
}
// this is called pickerView1 because it would conflict with the above
// function if called pickerView
func pickerView1(_ languagePicker: UIPickerView,
didSelectRow row1: Int,
inComponent component: Int) {
infoListInit.requestInfoList[6] = (languagePickerValues[row1])
}
performSegue(withIdentifier: "pickersDone", sender: nil)
}

There is a mistake in your code, the Delegate indicates that when a new row is selected in the UIPickerView, the function pickerView(_:didSelectRow:inComponent:) will be called (the argument name doesn't matter).
In your case in when any of the pickers select a new row pickerView(_:didSelectRow:inComponent:) is called with the picker passed as arguments in the firs position. You should check which picker was modified and then change your logic.
In your case:
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView == helpTypePicker {
infoListInit.requestInfoList[5] = helpTypePickerValues[row]
} else {
infoListInit.requestInfoList[6] = languagePickerValues[row]
}
}

Related

How to get data selected from UIPickerView and display it on a different View Controller?

I would like to show a user different screens depending on what they choose in a UIPickerView. What would be the best way to implement this? Thanks!
import UIKit
class SelectKitViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var kitPickerView: UIPickerView!
let kits = ["Kit 1", "Kit 2"]
var chosenKit: String?
override func viewDidLoad() {
super.viewDidLoad()
kitPickerView.delegate = self
kitPickerView.dataSource = self
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return kits[row]
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return kits.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let value = kits[row]
chosenKit = value
}
#IBAction func continuePressed(_ sender: Any) {
performSegue(withIdentifier: "SelectReactionVolume", sender: nil)
}
}
I would like to perform a segue to another View Controller when continue is pressed. Once the user chooses a kit they will have to enter additional info about the kit selected.

Swift 4.2 - PickerView not showing Content

this code makes me really mad. I already read thousands of tutorials and stack overflow comments....
Please help me. The Picker just contains a blank grey screen.
Code here:
GenderPickerModel.swift
import UIKit
class GenderPickerModel: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
let genderPickerData: [String] = ["male", "female"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1;
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return genderPickerData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return genderPickerData[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
}
}
and used in a Controller:
#IBOutlet weak var gender: UITextField!
private var genderPickerView: UIPickerView?
override func viewDidLoad() {
super.viewDidLoad()
loadProfile()
prepareView()
}
func prepareView() {
genderPickerView = UIPickerView.init()
let gpModel = GenderPickerModel()
genderPickerView?.delegate = gpModel
genderPickerView?.dataSource = gpModel
gender.inputView = genderPickerView;
genderPickerView?.selectRow(0, inComponent: 0, animated: true)
genderPickerView?.reloadAllComponents()
}
First, you do not need to do the separate array of gender in pickerview class and you don't need to create the instance of pickerview.
From this, you can see your datasource in your custompickerview
/**
Controller code where you can create instantiate picker assign data
*/
class ViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
let genderPickerData : [String] = ["male", "female"]
override func viewDidLoad() {
super.viewDidLoad()
prepareView()
}
func prepareView() {
genderPickerView = UIPickerView()
let gpModel = GenderPickerModel()
gpModel.data = genderPickerData
gpModel.dataSource = gpModel
gpModel.delegate = gpModel
textField.inputView = gpModel
}
}
/**
Custom pickerview class where you can handle data
*/
import UIKit
class GenderPickerModel: UIPickerView, UIPickerViewDataSource, UIPickerViewDelegate {
var data = [String]()
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return data.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return data[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
}
}

My selector lines are only displaying one line in my Pickers. I'd like them to be like how the date picker is

For some reason I can't seem to get both selector lines in my pickers to show. They only seem to show one but the date picker is fine.
class HomeViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var linePicker: UIPickerView!
#IBOutlet weak var skuPicker: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
linePicker.delegate = self
linePicker.dataSource = self
skuPicker.delegate = self
skuPicker.dataSource = self
//passed over from previous view
var plantInfo = plantInformation
let totalNumberOfLines = plantInfo!["lines"].count
//populated the data
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if (pickerView.isEqual(linePicker)){
return lineInfo.count
} else {
return skusForPickerLine.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView.isEqual(linePicker) {
return lineInfo[row].lineNumber
} else {
return skusForPickerLine[row].sku_value
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let selectedValue = linePicker.selectedRow(inComponent: 0)
skusForPickerLine = lineInfo[selectedValue].skuInfo
skuPicker.reloadComponent(0)
}
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
// height of picker is 50
return CGFloat(50)
}
}

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

Resources