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()
}
}
Related
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)
}
I have three TextFields in a Viewcontroller. After clicking the first I want to use UIPickerview to select something. The second TF should open the keyboard and the third one should open UIDatepicker.
import UIKit
class NewCompetitionViewController: UIViewController, UITextViewDelegate,UIPickerViewDataSource, UIPickerViewDelegate{
#IBOutlet weak var programTextField: UITextField!
let program = ["Big Target - 60 Shots",
"Big Target - 30 Shots",
"Small Target - 40 Shots"]
var selectedProgram: String?
let datePicker = UIDatePicker()
#IBOutlet weak var locationTextField: UITextField!
#IBOutlet weak var dateTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
createProgramPicker()
createDatePicker()
}
#IBAction func saveButton(_ sender: UIButton) {
dismiss(animated: true)
}
#IBAction func cancelButton(_ sender: UIButton) {
dismiss(animated: true)
}
// PROGRAM PICKER
func createProgramPicker(){
let programPicker = UIPickerView()
let toolBarPP = UIToolbar()
programPicker.delegate = self
// Customizations
programPicker.backgroundColor = .white
toolBarPP.sizeToFit()
let spaceButtonPP = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButtonPP = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(dismissKeyboard))
toolBarPP.setItems([spaceButtonPP, doneButtonPP], animated: false)
//toolBarPP.isUserInteractionEnabled = true
programTextField.inputAccessoryView = toolBarPP
programTextField.inputView = programPicker
}
// DISMISS KEYBOARD
#objc func dismissKeyboard(){
self.view.endEditing(true)
}
// DATE PICKER
func createDatePicker(){
datePicker.datePickerMode = .date
datePicker.backgroundColor = .white
let toolbarDP = UIToolbar()
toolbarDP.sizeToFit()
// flexible Space Button and Done button
let spaceButtonDP = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButtonDP = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneClicked))
toolbarDP.setItems([spaceButtonDP, doneButtonDP], animated: false)
//toolbarDP.isUserInteractionEnabled = true
dateTextField.inputAccessoryView = toolbarDP
dateTextField.inputView = datePicker
}
#objc func doneClicked(){
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/YYYY"
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
dateTextField.text = dateFormatter.string(from: datePicker.date)
self.view.endEditing(true)
}
// Returns true after "Done" clicked
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Hide the keyboard
textField.resignFirstResponder()
return true
}
private func textFieldDidEndEditing(_ textField: UITextField){
locationTextField.text = textField.text
}
}
extension NewCompetitionViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return program.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return program[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedProgram = program[row]
programTextField.text = selectedProgram
}
}
I can start the simulation and the UIPickerview works. Also the input on the keyboard at the second textfield. But if I open the datePicker and I click the done-button the display slides up from the bottom to the top with a transparent blue look.
Here are some screenshots:
Main screen
Program selection
Date selection
Bluescreen after clicking done
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
}
I have two UiTextfield which are supposed to show different UiPickerView when clicked on a respective UiTextfield.......
so i used this
if(textField.isFirstResponder() == true)
to find which textfield has been clicked...this does not work
class ViewController: UIViewController, UIPickerViewDataSource , UIPickerViewDelegate {
var pickerData = ["11", "12", "13"]
var pickerDataOthr = ["ada","daad","ada","daad","ada","daad","ada","daad"]
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var textFieldTwo: UITextField!
#IBOutlet weak var tftw: UITextField!
func pickerCode(){
let picker: UIPickerView
picker = UIPickerView(frame: CGRectMake(0, 200, view.frame.width, 300))
picker.backgroundColor = .whiteColor()
picker.showsSelectionIndicator = true
picker.delegate = self
picker.dataSource = self
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.Default
toolBar.translucent = true
toolBar.tintColor = UIColor(red: 76/255, green: 217/255, blue: 100/255, alpha: 1)
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "donePicker")
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Plain, target: self, action: "donePicker")
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.userInteractionEnabled = true
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
var count: Int
if(textField.isFirstResponder() == true)
{
count = pickerData.count
}
else
{
count = pickerDataOthr.count
}
return count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
var stro:String
if(textField.isFirstResponder() == true)
{
stro = pickerData[row]
}
else
{
stro = pickerDataOthr[row]
}
return stro
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if(textField.isFirstResponder() == true)
{
textField.text = pickerData[row]
}
else
{
textFieldTwo.text = pickerDataOthr[row]
}
}
func donePicker(){
if(textField.isFirstResponder() == true)
{
textField.resignFirstResponder()
}
else
{
textFieldTwo.resignFirstResponder()
}
}
func canclePicker(){
if(textField.isFirstResponder() == true)
{
textField.resignFirstResponder()
}
else
{
textFieldTwo.resignFirstResponder()
}
}
}
Adding a tag to every textfield
var tagMaster: Int!
func setUpTag(){
textField.tag = 1
textField.delegate = self
textFieldtwo.tag = 2
textFieldtwo.delegate = self
}
and in the picker helper methods idetify the clicked picker by the picker tags. In place of
textField.isFirstResponder()
i used
textField.tag
I'm working on my first Swift ios application.
Can't get data from pickerData into my picker, but I only get question marks instead of real values. I guess it's something to do with delegate, but not sure what wrong.
import UIKit
import CoreData
class NewWorkoutController: UIViewController,UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var workoutDistance: UITextField!
let pickerData = ["11","12","13","14","15"]
// Data Sources
func numberOfComponentsInPickerView(distancePickerView: UIPickerView) -> Int {
return 1
}
func pickerView(distancePickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
// Delegates
func pickerViewReturnRow(distancePickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return pickerData[row]
}
func pickerViewText(distancePickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
workoutDistance.text = pickerData[row]
}
func doneDistancePicker() {
workoutDistance.resignFirstResponder()
}
func cancelDistancePicker() {
workoutDistance.resignFirstResponder()
}
#IBAction func textFieldDistanceEditing2(sender: UITextField) {
// Create picker view
var distancePickerView: UIPickerView
distancePickerView = UIPickerView(frame: CGRectMake(0, 200, view.frame.width, 300))
distancePickerView.backgroundColor = .whiteColor()
distancePickerView.showsSelectionIndicator = true
distancePickerView.delegate = self
distancePickerView.dataSource = self
// Create toolbar
var toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.Default
toolBar.translucent = true
toolBar.tintColor = UIColor(red: 76/255, green: 217/255, blue: 100/255, alpha: 1)
toolBar.sizeToFit()
// Create buttons
var doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "doneDistancePicker")
var spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
var cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Plain, target: self, action: "cancelDistancePicker")
// Assign buttons to toolbar
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.userInteractionEnabled = true
// Add pickerview and toolbar to textfield
workoutDistance.inputView = distancePickerView
workoutDistance.inputAccessoryView = toolBar
sender.inputView = distancePickerView
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
The signature for this function is wrong:
func pickerViewReturnRow(distancePickerView: UIPickerView,
titleForRow row: Int,
forComponent component: Int) -> String!
It should be
func pickerView(pickerView: UIPickerView,
titleForRow row: Int,
forComponent component: Int) -> String!
As a result that method (which provides titles for the rows in your picker) isn't getting called.
In all pickerView delegate method's signature, you replaced pickerView with your pickerView outlet that is distancePickerView which is not required. You should modify code inside delegate method's body because delegate methods are automatically called by swift compiler if we confirm your pickerView delegate and datasource to your ViewController class by writing code as:
pickerViewOutlet.delegate = self
pickerViewOutlet.dataSource = self
So just modify all pickerView delegate methods with its default signature then it will get called by compiler and data will display in it.