UIBarbuttonitem selector never gets triggered (Swift 3) - ios

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

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()
}
}

Swift - Programmatically create UIPickerView

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

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 // <—-

how to use a button to select data from pickerview (swift4)

I want to use a button to select the data from my picker view. Currently my code uses the button to dismiss the picker view but the button does not select anything from the picker view. The only way something is selected is if a scroll using the picker view. How can I use my button as the only way to submit the data for the picker view?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
picker.delegate = self
picker.dataSource = self
for textFieldObject in theScoreRound
{
textFieldObject.inputView = picker
let toolbar = UIToolbar(frame: CGRect(x: 0, y: UIApplication.shared.statusBarFrame.height, width: view.bounds.width, height: 44))
var items = [UIBarButtonItem]()
items.append( UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil) )
items.append( UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(self.doneAction)) )
items.append( UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil) )
toolbar.items = items
let fs = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let db = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(self.doneAction))
toolbar.setItems([fs,db],animated: false)
textFieldObject.inputAccessoryView = toolbar
}}
#objc func doneAction(){
view.endEditing(true)
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return numberX.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return numberX[row]
}
public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
for textField in theScoreRound {
if textField.isEditing {
textField.text = numberX[row]
}
}
self.view.endEditing(false)
}
#IBAction func enterScore(_ sender: Any) {
var total = 0
for view in theScoreRound {
if let text = view.text, let num = Int(text) {
total += num
}
}
fighterAScore.text = String(total)
}
You need to use the UIPickerView selectedRow(inComponent: <#T##Int#>) method where you pass the component number in this case 0 because in your UIPickerDataSource you are returning 1 in the numberOfComponents method
Example Code
#IBAction func pickerDataAction(_ sender: Any) {
let selectedRow = self.pickerView.selectedRow(inComponent: 0)
let desiredValue = numberX[selectedRow]
}

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