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
Related
I have encountered some synchronisation/graphic update problems with my UIPickerView.
I want a view with 2 components, where the content of the second component depends on the selected row of the first component.
My code is inspired from: Swift UIPickerView 1st component changes 2nd components data
However, while it seems to work, sometimes (not every time) there are some visual problems, as seen on the screenshots below. (on the second screenshot, you can see that the rows of the second component are not really correct, and are a mix of the rows from the first and the second component)
Here is the code:
import UIKit
class AddActivityViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var typePicker: UIPickerView!
var pickerData: [(String,[String])] = []
override func viewDidLoad() {
super.viewDidLoad()
self.typePicker.delegate = self
self.typePicker.dataSource = self
pickerData = [("sport",["bike", "run", "soccer", "basketball"]),
("games",["videogame", "boardgame", "adventuregame"])]
// not sure if necessary
typePicker.reloadAllComponents()
typePicker.selectRow(0, inComponent: 0, animated: false)
// pickerData = [("sport",["bike", "run", "soccer"]),
// ("games",["videogame", "boardgame", "adventuregame"])]
}
// number of columns in Picker
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
// number of rows per column in Picker
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
print("function 1 called")
if component == 0 {
return pickerData.count
} else {
let selectedRowInFirstComponent = pickerView.selectedRow(inComponent: 0)
return pickerData[selectedRowInFirstComponent].1.count
}
}
// what to show for a specific row (row) and column (component)
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
print("function 2 called with values: component: \(component), row: \(row)")
if component == 0 {
// refresh and reset 2nd component everytime another 1st component is chosen
pickerView.reloadComponent(1)
pickerView.selectRow(0, inComponent: 1, animated: true)
// return the first value of the tuple (so the category name) at index row
return pickerData[row].0
} else {
// component is 1, so we look which row is selected in the first component
let selectedRowInFirstComponent = pickerView.selectedRow(inComponent: 0)
// we check if the selected row is the minimum of the given row index and the amount of elements in a given category tuple array
print("---",row, (pickerData[selectedRowInFirstComponent].1.count)-1)
let safeRowIndex = min(row, (pickerData[selectedRowInFirstComponent].1.count)-1)
return pickerData[selectedRowInFirstComponent].1[safeRowIndex]
}
//return pickerData[component].1[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// This method is triggered whenever the user makes a change to the picker selection.
// The parameter named row and component represents what was selected.
}
}
Is this a problem with my code or generally a complicated aspect of UIPickers that can not be trivially solved?
Additionally, is there a nicer way to develop this functionality?
I solved the error, however I do not understand why this solves it.
The solution is to imlement the func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)method, which I did not believe to be necessary just to show the fields.
In other words, just add this to my existing code:
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if component == 0 {
pickerView.reloadComponent(1)
} else {
let selectedRowInFirstComponent = pickerView.selectedRow(inComponent: 0)
print(pickerData[selectedRowInFirstComponent].1[row])
}
}
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:).
I have problem with a picker view that appears empty when I make it in second view controller.(image1).
When I make it in the first view controller that work fine.
two view controller and pickerview
code:
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate {
var civilite = ["Madame","Monsieur","Mademoiselle"]
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return civilite.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String!{
return civilite[row]
}
}
Xcode 6.4
I found the solution.
I add new file "Cocoa touch class" (Formulaire.swift) I change the custom class of the second view controller to be "Formulaire" [Custom class][1]
[1]: http://i.stack.imgur.com/H4Nip.png
I deplace the code in this file and is work fine.
Thanks
I keep getting an "'-[UITableView numberOfComponentsInPickerView:]: unrecognized selector sent to instance" error referencing a method in one of my custom UITableViewCell classes, and I can't seem to figure out why. I've searched through stack overflow but can't find an answer related to my situation. Any ideas? Thanks!
public class PickerTableViewCell:UITableViewCell, UIPickerViewDataSource, UIPickerViewDelegate {
var pickerData:[Array<Int>] = []
#IBOutlet weak var picker: UIPickerView!
public func configure(data:[Array<Int>]) {
pickerData = data
}
// Picker functions
public func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return pickerData.count
}
public func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData[component].count
}
public func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return String(pickerData[component][row])
}
}
If you look at the error message you see that the method numberOfComponentsInPickerView: was invoked on a UITableView instance.
So you ask the question "why would that method be invoked on a UITableView?"
The method in question is a picker view data source method, so that means that somewhere you assigned a UITableView as a picker view's data source, so that when the picker view was displayed the method call was made against a class (UITableView) that hadn't implemented the delegate method.
In your case it was a simple drag-drop error in Interface Builder.
I am currently working on a small project and i have a viewController that has 4 textFields which 3 work ok. They take String objects. However, the 4th textField is supposed to bring up a UIPickerView with 4 selectable items.
So far this is what i have in my controller that implements this:
#IBOutlet var pickerTextfield: UITextField!
#IBOutlet var itemPicker: UIPickerView! = UIPickerView()
The pickerTextfield is the UITextField object that is the 4th field.
The itemPicker is an unlinked UIPickerView that i want to create programatically.
Right below these properties, i have an array of items for the UIPickerView object:
var seasonalItems = ["Spring", "Summer", "Fall", "Winter"]
In my viewDidLoad method i have this as follow:
itemPicker.hidden = true;
pickerTextfield.text = seasonalItems[0]
pickerTextfield.delegate = self
And the rest of the implementation:
// Below these lines is the implementation of the Picker
func numberOfComponentsInPickerView(pickerView: UIPickerView!) -> Int{
return 1
}
// returns the # of rows in each component..
func pickerView(pickerView: UIPickerView!, numberOfRowsInComponent component: Int) -> Int{
return seasonalItems.count
}
func pickerView(pickerView: UIPickerView!, titleForRow row: Int, forComponent component: Int) -> String! {
return seasonalItems[row]
}
func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int)
{
pickerTextfield.text = seasonalItems[row]
itemPicker.hidden = true;
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
itemPicker.hidden = false
return false
}
So the end result from this is when i tap the pickerTextfield object in the app, it shows the first item of the array (Spring) but in text within the UITextField object but it does not show the UIPickerView object with the other selectable items where i could select one and then hide it when selected.
My question is, where or what am i doing wrong here? i been trying to figure this out on my own but i do not seem to get good clear examples with Swift and storyboards. I much rather not drag a UIPickerView in the storyboard but rather the way i attempted to implement. Thanks
You can give UIPickerView as inputView for your TextField in which you want to show picker view.
You also do not need to initially hide picker view in this case.
pickerTextfield.inputView = itemPicker
When you use UIPickerView as inputView of any UITextField then when you tap on the TextField instead of default keypad PickerView will show.