textFieldDidEndEditing not firing when pickerviiew used in swift3 - ios

The text field delegate method textFieldDidEndEditing is not firing when picker view is used in Swift 3. How can I call it? There is no button to dynamically call the delegate.
You can see my code below.
import UIKit
class ThroewViewController: UIViewController,UIPickerViewDelegate,UIPickerViewDataSource,UITextFieldDelegate {
#IBOutlet weak var pickerText: UITextField!
let thePicker = UIPickerView()
var dashTitle_Arr = ["One","Two","Three","Four","Five","Six"]
override func viewDidLoad() {
super.viewDidLoad()
pickerText.delegate = self
thePicker.dataSource = self
thePicker.delegate = self
pickerText.inputView = thePicker
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return dashTitle_Arr .count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return dashTitle_Arr [row] }
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
pickerText.text = dashTitle_Arr [row]
}
func textFieldDidEndEditing(_ textField: UITextField) {
addIntoArray(text: textField.text)
}
func addIntoArray(text: String?) {
guard let text = text, text.characters.count > 0 else {
return
}
dashTitle_Arr.append(text)
thePicker.reloadAllComponents()
}
}

There is a property of picker-view is accessoriesView. Create a tool bar with done or cancel button and set it in the picker view's assessoriesView.
In the toolbar button action write the textfield.resignFirstResponder()
After that the textFieldDidEndEditing delegate method fired
It works fine for me. Hope it will helps you. Thank you

Related

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

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

Problem on displaying UIPickerView value on TextEditor swift

I'm having a problem displaying a value selected from a UIPickerView on a UITextField. I added all required functions to make it work but the textfield doesn't get updated.
Here is the ViewController.swift code
#IBOutlet weak var requestDestination: UITextField!
var itemSelected : String?
var pickerData = ["Bollate" , "Baranzate" , "Garbagnate" , "Novate Milanese" , "Paderno Dugnano" , "Certosa"]
override func viewDidLoad() {
super.viewDidLoad()
let thePicker = UIPickerView()
thePicker.delegate = self
thePicker.dataSource = self
requestDestination.inputView = thePicker
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)
}
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]
}
private func pickerView( pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
itemSelected = pickerData[row]
requestDestination.text = itemSelected
}
#objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
requestDestination.resignFirstResponder()
}
I attached a screenshot where i show the first TextEdit that doesn't get the value from PickerView.
You have the wrong didSelectRow signature so it is never called. You missed the _. Let Xcode complete the methods for you instead of trying to type them yourself.
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

UIPickerView showing empty grey box Swift

I haven't a whole lot of code, so I might as well copy it here.
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource{
var buildings = ["BankBuilding", "Cinema" , "CornerShop", "Greg's House"]
#IBOutlet weak var buildText: UITextField!
var buildPickers:UIPickerView = UIPickerView()
override func viewDidLoad() {
super.viewDidLoad()
buildPickers = UIPickerView()
buildPickers.delegate = self
buildPickers.hidden = true;
buildText.inputView = buildPickers
buildText.text = buildings[0]
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
println("Count: \(buildings.count)")
return buildings.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
println("creating title: \(buildings[row])")
return buildings[row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
println("Selected: \(buildings[row])")
buildText.text = buildings[row]
buildPickers.hidden = true;
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
buildPickers.hidden = false
return false
}
}
The print statements are correct. For numberOfRows... and titleForRow it is printing the correct Strings.
But there is no prints for didSelectRow because, well, I can't select a row.
This is what I get:
You can ignore the Google Map in the background, that shouldn't interfere with the Picker View and is just set up in the StoryBoard.
The Grey window appears when I click on the textField but never shows any content. But the print statements say otherwise.
Does anyone know why this is the case?
Just add this line in your viewDidLoad method:
buildPickers.dataSource = self
And your code will be:
override func viewDidLoad() {
super.viewDidLoad()
buildPickers = UIPickerView()
buildPickers.delegate = self
buildPickers.dataSource = self
buildPickers.hidden = true;
buildText.inputView = buildPickers
buildText.text = buildings[0]
}
And it will show your data.
UPDATE:
It is not showing because you set it hidden in your viewDidLoad.
Just remove this line from your code:
buildPickers.hidden = true
Here is your working code:
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate{
var buildings = ["BankBuilding", "Cinema" , "CornerShop", "Greg's House"]
#IBOutlet weak var buildText: UITextField!
var buildPickers:UIPickerView = UIPickerView()
override func viewDidLoad() {
super.viewDidLoad()
buildPickers = UIPickerView()
buildPickers.delegate = self
buildPickers.hidden = true
buildText.delegate = self //set delegate for textField
buildText.inputView = buildPickers
buildText.text = buildings[0]
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
println("Count: \(buildings.count)")
return buildings.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
println("creating title: \(buildings[row])")
return buildings[row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
println("Selected: \(buildings[row])")
buildText.text = buildings[row]
buildPickers.hidden = true;
}
//this method will call when you click on textField
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
buildPickers.hidden = false
return true
}
}
Is the delegate set on the text field? Are you getting the callback which you use to un-hide the picker?

UIPickerView best practice?

One short question: on a registration process I would like to ask the user to choose a value from a list of values.
Is it the right way to use a view Controller adding there all text fields and for the values a picker view? As the picker view needs so much space in between the text fields area I wonder what the best practice in this case would be?
this is my code so far:
class RegisterViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource{
#IBOutlet weak var gradeTextField: UITextField!
#IBOutlet weak var gradePicker: UIPickerView!
let gradePickerValues = ["5. Klasse", "6. Klasse", "7. Klasse"]
func numberOfComponentsInPickerView(pickerView: UIPickerView!) -> Int{
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return gradePickerValues.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return gradePickerValues[row]
}
func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int){
gradeTextField.text = gradePickerValues[row]
self.view.endEditing(true)
}
override func viewDidLoad() {
super.viewDidLoad()
statusMessageLabel.hidden = true
gradePicker.dataSource = self
gradePicker.delegate = self
gradePicker.hidden = true
gradeTextField.inputView = UIPickerView()
gradeTextField.text = gradePickerValues[0]
}
The pickerview is hidden at the beginning and appears only when I select the text field, this is fine so far... But the the picker view is empty...
It depends on controller appearance. If there only one choose action per screen it will be better to put Table View on it and selected row will be current selection.
If screen has multiply fields, that user should act with, then, in my opinion, it's better to put label + button above it and when user press this button you just shows Picker View from screen bottom. When user select any row in Picker View you change label text, but don't hide picker itself, it should be done by pressing "Done" button you place above.
Hope this helps.
Update:
Your problem because you just forget to set dataSource property of UIPickerView
Just do: gradePicker.dataSource = self in viewDidLoad()
And don't forget to implements protocol here: class RegisterViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource
Update 2:
Finally made it. If you add UIPickerView in inputView of your textFiled, then It should NOT be in IB. So you could remove it from storyboard (or .xib, if you use it).
Then change code to be something like this:
class RegisterViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var gradeTextField: UITextField!
var gradePicker: UIPickerView!
let gradePickerValues = ["5. Klasse", "6. Klasse", "7. Klasse"]
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return gradePickerValues.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return gradePickerValues[row]
}
func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int){
gradeTextField.text = gradePickerValues[row]
self.view.endEditing(true)
}
override func viewDidLoad() {
super.viewDidLoad()
gradePicker = UIPickerView()
gradePicker.dataSource = self
gradePicker.delegate = self
gradeTextField.inputView = gradePicker
gradeTextField.text = gradePickerValues[0]
}
}
First set delegate
UIPickerViewDataSource,UIPickerViewDelegate
set IBOutlet for UIPickerView
#IBOutlet weak var pickerView: UIPickerView!
Take an array for data
var arrayFruits = [String]()
Write this code on viewDidLoad()
arrayFruits = ["Apple","Banana","Orange","Grapes","Watermelon"]
self.pickerView.dataSource = self
self.pickerView.delegate = self
Write picker view delegate methods:
//MARK: - Pickerview method
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return arrayFruits.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return arrayFruits[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.labelFruit.text = arrayFruits[row]
}
100% working and tested

Swift-XCode - How to let Text Field have set values the user can choose from?

I understand how the normal text field works where the user can input their own text, but is there a way where the user clicks the text field and it comes up with some options, such as "Hello", "Bye", and "Goodnight"?
It's sort of like a placeholder with more options, and the placeholder really isn't in effect in this because when the user clicks the text field, the options pop up for text to select, and the user can select the text and that text will be used in the text field.
Thanks!
You want to use UIPickerView and the inputView property of UITextField
Implement the methods like:
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate
{
#IBOutlet weak var textField: UITextField!
var dataObject : [String] = ["Hello","Bye","Good Night"];
override func viewDidLoad()
{
super.viewDidLoad()
let picker = UIPickerView()
picker.delegate = self
picker.dataSource = self
self.textField.inputView = picker
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
{
return 1;
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{
return self.dataObject.count;
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String!
{
return self.dataObject[row];
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
self.textField.text = self.dataObject[row];
self.textField.endEditing(true)
}
}

Resources