Swift - Programmatically create UIPickerView - ios

I created PickerView, but this does not open the PickerView I created. Where do I make a mistake? Why PickerView doesn't open. I added picker view in the text field but it doesn't work. I added it to viewDidLoad, but when I click a text field, picker view does not open.
class EnergyChart: UIViewController , UIPickerViewDelegate, UIPickerViewDataSource {
var picker = UIPickerView()
var gradePickerValues1 : [String] = ["...", ...]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return gradePickerValues1.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gradePickerValues1[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int){
getDevice.text = gradePickerValues1[row]
switch row {
case 0: break
default: break
}
self.view.endEditing(true)
}
#objc func cancelTapped() {
self.view.endEditing(true)
}
let getDevice: UITextField = {
let textFieldframe = CGRect()
let textField2 = SkyFloatingLabelTextFieldWithIcon(frame: textFieldframe, iconType: .image)
...
return textField2
}()
#objc func GetDevice() {
self.getDevice.text = self.gradePickerValues1[0]
}
override func viewDidLoad() {
super.viewDidLoad()
picker.backgroundColor = .white
picker.showsSelectionIndicator = true
picker.delegate = self
picker.dataSource = self
getDevice.inputView = picker
GetDevice()
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
toolBar.tintColor = UIColor(..)
toolBar.sizeToFit()
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "İptal", style: UIBarButtonItem.Style.plain, target: self, action: #selector(cancelTapped))
toolBar.setItems([cancelButton, spaceButton], animated: false)
toolBar.isUserInteractionEnabled = true
getDevice.inputAccessoryView = toolBar
view.addSubview(getDevice)
getDevice.snp.makeConstraints { (make) in
make.centerX.equalTo(view).offset(50)
make.top.equalTo(view).offset(510)
make.height.equalTo(50)
make.width.equalTo(200)
}

Related

Picker buttons do not show up

I am attempting to add "done" and "cancel" buttons in a toolbar above a pickerView that will be used to change the value of a label. The label should only be changed when "done" is clicked not when UIPicker received rowSelected.
I can't understand why my "done" and "cancel" buttons do not show above my picker? I'm sure this will be marked as duplicate, but I've done something very similar in Swift 4, and this doesn't seem to work in Swift 5.
import UIKit
class ViewController: UIViewController, UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var freq: UILabel!
var freqOptions = ["Hz", "kHz", "MHz"]
var freqPicker = UIPickerView()
#IBOutlet weak var freqTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
freqPicker = UIPickerView( frame: CGRect(x: 0, y: 100, width: self.view.frame.width, height: 216) )
freqPicker.backgroundColor = UIColor.white
freqPicker.delegate = self
freqPicker.dataSource = self
freqPicker.isHidden = true
let toolBar = UIToolbar()
let cancelItem = UIBarButtonItem(
title: "Cancel",
style: .plain,
target: self,
action: #selector(cancelFreqInput)
)
let middleItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneItem = UIBarButtonItem(
title: "Done",
style: .done,
target: self,
action: #selector(confirmFreqInput)
)
toolBar.setItems( [cancelItem, middleItem, doneItem], animated : false )
toolBar.sizeToFit()
view.addSubview(freqPicker)
let freqTap = UITapGestureRecognizer(target: self, action: #selector(freqTap(gestureReconizer:)))
freq.addGestureRecognizer(freqTap)
freqTextField.inputView = freqPicker
freqTextField.inputAccessoryView = toolBar
freqTextField.isHidden = true
freq.isUserInteractionEnabled = true
}
#objc func cancelFreqInput() {
freqTextField.resignFirstResponder()
freq.text = "Hz"
freqTextField.isHidden = true
}
#objc func confirmFreqInput() {
freqTextField.resignFirstResponder()
freqTextField.isHidden = true
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return freqOptions.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
freq.text = freqOptions[row]
self.view.endEditing(true)
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return freqOptions[row]
}
#objc func freqTap(gestureReconizer: UITapGestureRecognizer) {
freqPicker.isHidden = false
}
}
you don't need to add a picker as a subview. You just need to set it Like an input view (and you already done it). I modified you code. You can just compare and check what was wrong there
class ViewController: UIViewController, UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var freq: UILabel!
var freqOptions = ["Hz", "kHz", "MHz"]
var freqPicker = UIPickerView()
#IBOutlet weak var freqTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
freqPicker = UIPickerView()
freqPicker.backgroundColor = UIColor.white
freqPicker.delegate = self
freqPicker.dataSource = self
// freqPicker.isHidden = true
let toolBar = UIToolbar()
let cancelItem = UIBarButtonItem(
title: "Cancel",
style: .plain,
target: self,
action: #selector(cancelFreqInput)
)
let middleItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneItem = UIBarButtonItem(
title: "Done",
style: .done,
target: self,
action: #selector(confirmFreqInput)
)
toolBar.setItems( [cancelItem, middleItem, doneItem], animated : false )
toolBar.sizeToFit()
// view.addSubview(freqPicker)
let freqTap = UITapGestureRecognizer(target: self, action: #selector(freqTap(gestureReconizer:)))
freq.addGestureRecognizer(freqTap)
freqTextField.inputView = freqPicker
freqTextField.inputAccessoryView = toolBar
freqTextField.isHidden = true
freq.isUserInteractionEnabled = true
freqPicker.reloadComponent(0)
}
#objc func cancelFreqInput() {
freqTextField.resignFirstResponder()
freq.text = "Hz"
freqTextField.isHidden = true
}
#objc func confirmFreqInput() {
freq.text = freqOptions[freqPicker.selectedRow(inComponent: 0)]
self.view.endEditing(true)
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return freqOptions.count
}
// func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// freq.text = freqOptions[row]
// self.view.endEditing(true)
// }
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return freqOptions[row]
}
#objc func freqTap(gestureReconizer: UITapGestureRecognizer) {
freqTextField.becomeFirstResponder()
}
}

incorrect array showing in UIPickerView

I have two UIPickerviews that appear on one ViewController. I have tried to follow the following tutorial.
I have followed the suggestion in that I have tagged each of the UITextFields (I have 4 in total). See the the image.
Below is the code for the UIPickerViews.
extension DriverViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView.tag == 0 {
return tracks.count
} else {
return drivers.count
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView.tag == 0 {
return "\(tracks[row])"
} else {
return "\(drivers[row])"
}
}
The problem I am having is that the tracks array appear on all of the UITextfields.
Below is the code for each of the Arrays and the title of the UIPickerView.
override func viewDidLoad() {
super.viewDidLoad()
tracks = ["Melbourne", "Manama", "Shanghai", "Baku",
"Barcelona", "Monaco", "Montreal","Le Castellet","Spielberg",
"Silverstone","Hockenheim","Budapest","Francorchamps","Monza","Singapore","Sochi","Suzuka","Austin","Interlagos","Abu Dhabi"]
drivers = ["Lewis Hamilton","Antonio Giovinazzi","Kimi Raikkonen","Charles Leclerc","Sebastian Vettel","Romain Grosjean","Kevin Magnussen","Lando Norris",
"Carlos Sainz","Valtteri Bottas","Sergio Perez","Lance Stroll","Pierre Gasly","Max Verstappen","Nico Hulkenberg","Daniel Ricciardo","Alexander Albon","Daniil Kvyat","Robert Kubica","George Russell"]
createTrackPicker()
createDriverPicker()
createToolBar()
// Do any additional setup after loading the view.
}
func createTrackPicker() {
let trackPicker = UIPickerView()
trackPicker.delegate = self
TrackTextField.inputView = trackPicker
}
func createDriverPicker() {
let driverPicker = UIPickerView()
driverPicker.delegate = self
firstTextField.inputView = driverPicker
secondTextField.inputView = driverPicker
thirdTextField.inputView = driverPicker
}
func createToolBar() {
let toolBar = UIToolbar()
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(ViewController.dismissKeyboard))
toolBar.setItems([doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
TrackTextField.inputAccessoryView = toolBar
firstTextField.inputAccessoryView = toolBar
secondTextField.inputAccessoryView = toolBar
thirdTextField.inputAccessoryView = toolBar
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
You forgot the tag.
func createDriverPicker() {
let driverPicker = UIPickerView()
driverPicker.tag = 1 // <—-

UIBarbuttonitem selector never gets triggered (Swift 3)

Sometimes the simplest things prove the hardest to work out! The picker is displayed when users select the user location text field but the selectors are not working. Gone through SO and Apple docs but can't work out why this is.
let locationPicker = UIPickerView()
var locationData = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Set textfield delegate
userID.delegate = self
userLocation.delegate = self
// Set up picker view for location selection
locationPicker.frame = CGRect(x:0, y: self.view.bounds.height, width: self.view.bounds.width, height: 140)
locationPicker.showsSelectionIndicator = true
let doneButton = UIBarButtonItem(title: "done", style: .plain, target: self, action: #selector(self.closePicker(sender:)))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "cancel", style: .plain, target: self, action: #selector(self.closePicker(sender:)))
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.blackOpaque
toolBar.isTranslucent = true
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
userLocation.inputView = locationPicker
userLocation.inputAccessoryView = toolBar
// Load locations into array
let ref: FIRDatabaseReference = FIRDatabase.database().reference().child("venues")
ref.observe(.value, with: { snapshot in
// Pull out the keys to represent locations
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshots {
print("snap key, \(snap.key) and snap value \(snap.value)")
let loc : String = snap.key
self.locationData.append(loc)
}
}
// Now stick the array of locations into the picker view
self.locationPicker.dataSource = self
self.locationPicker.delegate = self
self.locationPicker.reloadAllComponents()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.endEditing(true)
return false
}
func closePicker(sender: AnyObject) {
print("Close picker")
self.locationPicker.isHidden = true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if let iText = userID.text, let lText = userLocation.text, !iText.isEmpty, !lText.isEmpty
{
print("We have data")
// loginButton.isUserInteractionEnabled = true
// loginButton.alpha = 1.0
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return locationData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return locationData[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
userLocation.text = locationData[row]
}

fatal error: Index out of range in swift while taking options from uipicker

I have 3 text field like to select gender, country, state. And I am using UIPicker to get the input values from UIPicker. But now when I press gender UITextField to open UIPickerenter code here, the UIPickerenter code here is showing with no data. But the same UIPicker I am using for the country, state. that time it's showing the data with UIPicker for both countries, state text field. Can anyone please help me out. How to solve this problem.
Error :
fatal error: Index out of range
If I press in uipicker option view only its crashing.
My code :
I am getting a crash in this class file :
import Foundation
import SwiftCountryPicker
class DataPicker: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
var dataPicker: UIPickerView!
var inputText:UITextField!
var parent:UIViewController!
var pickerData: [String]!
var feetStr = String()
var inchStr = String()
private var _selectedValue: String!
var selectedvalue: String {
return _selectedValue ?? String()
}
func showPicker(parent:UIViewController,inputText:UITextField, data: [String], selectedValueIndex: Int){
self.inputText = inputText
self.parent = parent
pickerData = data
if dataPicker == nil {
dataPicker = UIPickerView(frame: CGRectMake(0,0,parent.view.frame.size.width, 216))
dataPicker.backgroundColor = UIColor.whiteColor()
dataPicker.dataSource = self
dataPicker.delegate = self
dataPicker.selectRow(selectedValueIndex, inComponent: 0, animated: true)
_selectedValue = pickerData.count > 0 ? pickerData[selectedValueIndex] : ""
}
inputText.inputView = dataPicker
// ToolBar
let toolBar = UIToolbar()
toolBar.barStyle = .Default
toolBar.translucent = true
toolBar.tintColor = UIColor(hex: "B12420")
toolBar.backgroundColor = UIColor.whiteColor()
toolBar.sizeToFit()
// Adding Button ToolBar
let doneButton = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: #selector(DataPicker.doneClick))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: #selector(DataPicker.cancelClick))
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.userInteractionEnabled = true
inputText.inputAccessoryView = toolBar
}
func doneClick() {
inputText.text = _selectedValue
inputText.resignFirstResponder()
}
func cancelClick() {
inputText.resignFirstResponder()
}
func numberOfComponentsInPickerView(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) {
_selectedValue = pickerData[row]
}
}
In this line :
func pickerView(pickerView: UIPickerView, didSelectRow row: Int,
inComponent component: Int) {
_selectedValue = pickerData[row]
}
And my text field delegate for press the texfield:
extension UserInfoViewController:UITextFieldDelegate{
func textFieldDidBeginEditing(textField: UITextField) {
selectedText = textField
else if textField == genderss {
ctDataPicker = DataPicker()
let indexPos = genders.indexOf(genderss.text!) ?? 0
ctDataPicker.showPicker(self, inputText: textField, data: genders,selectedValueIndex: indexPos)
}
}
}
UIPickerViewDataSource method didSelectRow is changed in Swift 4:
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) {
TextField.text = myPickerData[row]
}
Try changing the line crashing _selectedValue to a textfield example
TextField.text = myPickerData[row]
Check Apple Documentation on UIPickerView.

PickerView doesn't show any value. It gives warning like no index path for table cell being reused?

I have created a UIView class in which I have declared pickerView and implement all necessary delegates. When I click on textfield, no value is shown in pickerView and warning comes in log
no index path for table cell being reused.
Please help me find out the solution of this.
import UIKit
class CustomPickerView: UIView, UIPickerViewDelegate, UIPickerViewDataSource {
var pickerView = UIPickerView()
var pickerString: String?
var pickerArray = NSArray()
class var instance: CustomPickerView
{
let pickerVC = CustomPickerView()
return pickerVC
}
override init(frame: CGRect) {
super.init(frame : frame)
pickerView.delegate = self
pickerView.dataSource = self
pickerView.backgroundColor = UIColor.yellowColor()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setValueOfPicker(text: String, array: NSArray, textField: UITextField) -> Void {
pickerString = text
pickerArray = array
setPicker(textField)
pickerView.reloadAllComponents()
pickerView.selectRow(0, inComponent: 0, animated: true)
}
//MARK:
//MARK: Piker View Delegate & DataSource
//MARK:
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerArray.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerString == "country" {
return pickerArray[row].valueForKey("country") as? String
}
else if pickerString == "printCoupon"
{
return pickerArray[row] as? String
}
return nil
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
}
func setPicker(dataTextField: UITextField)
{
dataTextField.inputView = pickerView;
let doneToolbar: UIToolbar = UIToolbar()
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: #selector(donePickerAction))
let cancle: UIBarButtonItem = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Done, target: self, action: #selector(canclePickerAction))
var items = [UIBarButtonItem]()
items.append(cancle)
items.append(flexSpace)
items.append(done)
doneToolbar.sizeToFit()
doneToolbar.items = items
dataTextField.inputAccessoryView = doneToolbar
}
Try to implement this method
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView
{
let pickerLabel = UILabel()
if pickerString == "country" {
pickerLabel.text = pickerArray[row].valueForKey("country") as? String
}
else if pickerString == "printCoupon"
{
pickerLabel.text = pickerArray[row] as? String
}
pickerLabel.textAlignment = NSTextAlignment.Center
return pickerLabel
}

Resources