UIPickerView reports an incorrect row - ios

When I traverse this UIPickerView from top down, the row is reported correctly for each element. However, traversing the UIPickerView from bottom to top, when "Choice 3" is tapped, the row resets itself to zero where it should actually be 2. I added the label for visual proof -- it flashes "2", then resets itself to zero when traversing the UIPickerView as described. Obviously, not being able to depend on the relationship between display element and actual row being accurate breaks things. No idea why this isn't working...
class ViewController3: UIViewController, UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var picker: UIPickerView!
#IBOutlet weak var textLabel: UILabel!
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return 4
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView,titleForRow row: Int,forComponent component: Int) -> String? {
textLabel.text = String(row)
return pickerValues[row]
}
let pickerValues = ["Choice 1", "Choice 2", "Choice 3","Choice 4"]

If the goal is to change a label every time the user turns the "wheel" of the picker view, implement the delegate method pickerView(_:didSelectRow:inComponent:).

Related

Treat an UIPickerView like a combo/select box

I'm working with XCode 8.2.1, Swift 3 and iOS10.
I've a list of items with the following format:
ID | Name
---------
1 | John
2 | Maria
3 | Peter
4 | Roger
The code looks like this:
var formsList = [1:"John", 2:"Maria", 3:"Peter", 4:"Roger"]
What I want to do is to set that data into an UIPickerView, so when someone chooses for example John, the ID 1 is returned, or if someone chooses Peter, the ID 3 is returned.
I do other stuff once I get that ID, that's why I need it.
Any idea or suggestion on how I can achieve this?
Thanks!
You just need to sort your dictionary by its keys and use it as your picker data source:
let formsList = [1:"John", 2:"Maria", 3:"Peter", 4:"Roger"]
let dataSource = formsList.sorted{$0.key<$1.key}
This way you have all your dictionary names sorted in an array including their IDs. Your picker should look something like this:
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var pickerView: UIPickerView!
#IBOutlet weak var label: UILabel!
let formsList = [1:"John", 2:"Maria", 3:"Peter", 4:"Roger"]
var dataSource: [(key: Int, value: String)] = []
override func viewDidLoad() {
super.viewDidLoad()
dataSource = formsList.sorted{$0.key<$1.key}
pickerView.delegate = self
pickerView.dataSource = self
label.text = "id: " + String(dataSource[pickerView.selectedRow(inComponent: 0)].key) + " - " + "name: " + dataSource[pickerView.selectedRow(inComponent: 0)].value
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return dataSource.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return dataSource[row].value
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
label.text = "id: " + String(dataSource[row].key) + " - " + "name: " + dataSource[row].value
}
}
sample
Your approach of using a dictionary of your data structure is problematic. Dictionaries are, by design, unordered.
There are lots of ways to do this. Most involve creating an array of some sort containing items for each entry from which you want the user to pick.
For example, create an array of tuples:
typealias NameTuple = (id: Int, name: String)
var namesArray: [NameTuple]
Feed your picker view with the name field of each entry in your array. When the user selects an item, use the selected index to fetch that tuple and then get the ID.
You could also use an array of structs, or an array of name objects.

Update Label by using pickerview and text field

I have a PickerView that deposit values. This values will be calculate with a user textfield input. The result will show in a label. That works for me.
By starting the app the textfield have a fix number of 1.
How can I now update my label automatically by use the Pickerview?
I read and try many things but it don´t works.
Maybe it is a little thing, but i don´t see it.
import UIKit
class BalkenbewehrungVC: UIViewController, UIPopoverPresentationControllerDelegate, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate {
// Deklarationen Pickerview
var multiplicator : Double = 0.0
let multiplicators = [0.0,6.0,8.0,10.0,12.0,14.0,16.0,20.0,25.0,26.0,28.0,30.0,32.0,36.0,40.0,50.0]
let PI = 3.1415
// Pickerview füllen
var pickerDataSource = ["---","Ø 6","Ø 8","Ø 10","Ø 12","Ø 14","Ø 16","Ø 20","Ø 25","Ø 26","Ø 28","Ø 30","Ø 32","Ø 36","Ø 40","Ø 50"]
// Picker im aktivieren
#IBOutlet weak var Pickerview: UIPickerView!
// Ausgabewert As = xxxx cm
#IBOutlet var AusgabePicker: UILabel!
// Eingabe Anzahl Stäbe
#IBOutlet var AnzahlStab: UITextField!
#IBAction func test(sender: UITextField) {
if AnzahlStab.text!.isEmpty {
AnzahlStab.text = "1"
let result1 = (multiplicator / 10) * (multiplicator / 10) * PI / 4 * 1
AusgabePicker.text! = String(format:"%.3f", result1)
} else {
let result = (multiplicator / 10) * (multiplicator / 10) * PI / 4 * (AnzahlStab.text! as NSString).doubleValue
// let resultString = "\(result)"
AusgabePicker.text = String(format:"%.3f", result)
}
}
// Picker - feste Reihen
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
// Picker - Aufaddierung neuer Reihen
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerDataSource.count
}
// Picker - Datenübernahme multiplicator in Picker
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerDataSource[row]
}
// Picker - Wertefestlegung Picker
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
multiplicator = multiplicators[row]
_ = NSNumberFormatter.localizedStringFromNumber(NSNumber(double: multiplicator), numberStyle:.DecimalStyle)
}
In the didSelectRow method for the pickerView, set the label's text to your newly calculated value.
Update: To update the label's text depending on the textField's input, inside your ViewController's viewDidLoad method, add this line
AnzahlStab.delegate = self
and then add the textFieldDidEndEditing method, and inside it update the label's text to the new value. This method is called when you are done with editing the text field.
Need to call function test in picker view didSelectRow. Or Simply Replace your didSelectRow with following code.
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
multiplicator = multiplicators[row]
_ = NSNumberFormatter.localizedStringFromNumber(NSNumber(double: multiplicator), numberStyle:.DecimalStyle)
self.test(AnzahlStab)
}
Hope this Answer will help you.

Making a drop down list using swift? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Improve this question
What is the library to make drop down menu in swift? I am new to Xcode and the Swift language, so can anyone please direct me on how to implement the drop down list in swift?
(Swift 3) Add text box and uipickerview to the storyboard then add delegate and data source to uipickerview and add delegate to textbox. Follow video for assistance
https://youtu.be/SfjZwgxlwcc
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
#IBOutlet weak var textBox: UITextField!
#IBOutlet weak var dropDown: UIPickerView!
var list = ["1", "2", "3"]
public func numberOfComponents(in pickerView: UIPickerView) -> Int{
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return list.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
self.view.endEditing(true)
return list[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.textBox.text = self.list[row]
self.dropDown.isHidden = true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == self.textBox {
self.dropDown.isHidden = false
//if you don't want the users to se the keyboard type:
textField.endEditing(true)
}
}
}
A 'drop down menu' is a web control / term. In iOS we don't have these. You might be better looking at UIPopoverController. Check out this tutorial for a bit of an insight to PopoverControllers
http://www.raywenderlich.com/29472/ipad-for-iphone-developers-101-in-ios-6-uipopovercontroller-tutorial
Unfortunately if you're looking to apply UIPopoverController in iOS9, you'll get a deprecated class warning. Instead you need to set your desired view's UIModalPresentationPopover property to achieve the same result.
Popover
In a horizontally regular environment, a presentation style
where the content is displayed in a popover view. The background
content is dimmed and taps outside the popover cause the popover to be
dismissed. If you do not want taps to dismiss the popover, you can
assign one or more views to the passthroughViews property of the
associated UIPopoverPresentationController object, which you can get
from the popoverPresentationController property.
In a horizontally compact environment, this option behaves the same as
UIModalPresentationFullScreen.
Available in iOS 8.0 and later.
Reference: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621355-modalpresentationstyle
You have to be sure to use UIPickerViewDataSource and UIPickerViewDelegate protocols or it will throw an AppDelegate error as of swift 3
Also please take note of the change in syntax:
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
is now:
public func numberOfComponents(in pickerView: UIPickerView) -> Int
The following below worked for me.
import UIkit
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet weak var textBox: UITextField!
#IBOutlet weak var dropDown: UIPickerView!
var list = ["1", "2", "3"]
public func numberOfComponents(in pickerView: UIPickerView) -> Int{
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return list.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
self.view.endEditing(true)
return list[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.textBox.text = self.list[row]
self.dropDown.isHidden = true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == self.textBox {
self.dropDown.isHidden = false
//if you don't want the users to se the keyboard type:
textField.endEditing(true)
}
}
}
Using UIPickerview is the right way to go to implement it according to Apple's Human Interface Guidelines
If you select drop down in mobile safari it will show UIPickerview to let the use choose drop down items.
Alternatively
you can use UIPopoverController till iOS 9 as its deprecated but its better to stick with UIModalPresentationPopover of view you want o show as well
you can use UIActionsheet to show the items but it's better to use UIAlertViewController and choose UIActionSheetstyle to show as the former is deprecated in latest versions

What is the meaning of "component" in a UIPickerView.selectedRowInComponent?

Using Swift in Xcode, I want to make:
1) A PICKER, with data from an array
2) A BUTTON, when pressed will update a LABEL with the text from a selected row of the PICKER
My code currently:
var array = ["Sydney", "London", "Washington", "Tokyo", "San Francisco"]
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return array.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return array[row]
}
#IBOutlet weak var PICKER: UIPickerView!
#IBOutlet weak var LABEL: UILabel!
#IBAction func BUTTON(sender: AnyObject) {
LABEL.text = array[PICKER.selectedRowInComponent(0)]
}
So far everything worked. But I have 2 questions:
1) Should I put a "0" in PICKER.selectedRowInComponent? What does it mean? Because it didn't work without a number or with any other number. Wouldn't that mean selecting only the first row (instead of selecting the row the user has selected)?
2) How do I make the PICKER to show the middle item of an array by default and not the first item when the app loads (e.g. Washington in this case)?
Pickers can have multiple wheels (components). For example, you might have separate wheels for each digit, or you might have day, month, and year wheels. They are numbered starting at 0. So "Component 0" is just the first wheel (and you only have one).
Selecting rows is done by calling selectRow(inComponent:animated:).
UIPickerView can have multiple wheels (named components), and are numbered starting at 0. For example, a picker view with 3 components looks like the following where
the first wheel ("6") is component 0
the second wheel ("00") is the component 1
the third wheel ("AM") is the component 2
Unrelated to question title, but selecting a row is done by calling selectRow(_:inComponent:animated:)
var array = ["Sydney", "London", "Washington", "Tokyo", "San Francisco"]
// code...
yourPicker.selectRow(array.count/2, inComponent: 0, animated: true);

Using the value on 1st component on UIPickerView to change the remaining components

just got some great help which made the UIPickerView wheels work perfectly but they I have been trying to get the data in the 2nd and 3rd components to change dependant on the position of the 1st component.
I can get through some println lines to work out that the variable that I pull out whatConversion has the correct value but I have no idea how to change the array and make the UIPickerView update with the new values.
Please help for my sanity and also I am going to have to put extra time in at work after spending nearly all day on these, what dozen lines of code.
Thanks in advance
Motty
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate {
#IBOutlet weak var picker1Label: UILabel!
#IBOutlet weak var picker2Label: UILabel!
#IBOutlet weak var bigPicker: UIPickerView!
var wheelContents:[[String]] = []
var length = ["metres","feet","yards","inches","mm","cm","miles"]
var volume = ["m3","US Gall","Imp Gall","Barrels", "cubic FT","litres"]
var conType = ["length","volume"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
bigPicker.delegate = self
wheelContents = [conType, length, length]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//For main selection of type of conversion
// returns the number of 'columns' to display.
func numberOfComponentsInPickerView(bigPicker: UIPickerView) -> Int{
return wheelContents.count
}
// returns the # of rows in each component..
func pickerView(bigPicker: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return wheelContents[component].count
}
func pickerView(bigPicker: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String!{
return wheelContents[component][row]
}
func pickerView(bigPicker: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
var whatConversion = wheelContents[0][bigPicker.selectedRowInComponent(0)]
switch(whatConversion){
case "length":
wheelContents = [conType, length, length]
bigPicker.numberOfRowsInComponent(wheelContents[component].count)
break
case "volume":
wheelContents = [conType, volume, volume]
break
default:
break
}
}
}
I am even happier I managed to figure this out myself by looking at the Class definitions and functions
used bigPicker.reloadAllComponents()

Resources