UIDatePicker on button tap - ios

So far I've only found date-picker bound to UITextField, but I need a date-picker which opens on UIButton tap in the same way as it does with the UITextField.
Is it possible? And if so, how? Thanks in advance.

#IBAction func BtnClicked(sender: AnyObject) {
var picker : UIDatePicker = UIDatePicker()
picker.datePickerMode = UIDatePickerMode.Date
picker.addTarget(self, action: "dueDateChanged:", forControlEvents: UIControlEvents.ValueChanged)
var pickerSize : CGSize = picker.sizeThatFits(CGSizeZero)
picker.frame = CGRectMake(0.0, 250, pickerSize.width, 460)
// you probably don't want to set background color as black
// picker.backgroundColor = UIColor.blackColor()
self.view.addSubview(picker)
}
func dueDateChanged(sender:UIDatePicker){
var dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.LongStyle
dateFormatter.timeStyle = NSDateFormatterStyle.NoStyle
self.myLabel.text = dateFormatter.stringFromDate(dueDatePickerView.date)
}

because i dont have enough reputation to comment , i am posting same answer of #iAnurag in Swift 4
#IBAction func UpdateDOBClick(_ sender: UIButton) {
let picker : UIDatePicker = UIDatePicker()
picker.datePickerMode = UIDatePickerMode.date
picker.addTarget(self, action: #selector(dueDateChanged(sender:)), for: UIControlEvents.valueChanged)
let pickerSize : CGSize = picker.sizeThatFits(CGSize.zero)
picker.frame = CGRect(x:0.0, y:250, width:pickerSize.width, height:460)
// you probably don't want to set background color as black
// picker.backgroundColor = UIColor.blackColor()
self.view.addSubview(picker)
}
#objc func dueDateChanged(sender:UIDatePicker){
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .none
dobButton.setTitle(dateFormatter.string(from: sender.date), for: .normal)
}

Here is another approach using .hidden feature of the controls. I use a button that changes the title when touched and hides/shows the date picker.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var showDate: UILabel!
#IBOutlet weak var myButtonx: UIButton!
#IBAction func myButton(sender: UIButton) {
if myButtonx.titleLabel?.text != "Done" {
// save the date for your need
showDate.text = "\(myDatePicker.date)"
myDatePicker.hidden = false
myButtonx.setTitle("Done",forState: UIControlState.Normal)
} else {
myDatePicker.hidden = true
myButtonx.setTitle("Pick Date",forState: UIControlState.Normal)
}
}
#IBOutlet weak var myDatePicker: UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
myDatePicker.hidden = true
myButtonx.setTitle("Pick Date",forState: UIControlState.Normal)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

private var datePicker: UIDatePicker?
#IBAction func dateFilterAction(_ sender: UIButton) {
if self.view.subviews.contains(where: { $0 is UIDatePicker }) {
self.datePicker?.removeFromSuperview()
dateFilter.setTitle("Datum", for: .normal)
} else {
datePicker = nil
setupDatePicker()
}
}
private func setupDatePicker() {
let picker = datePicker ?? UIDatePicker()
picker.datePickerMode = .date
if #available(iOS 13.4, *) {
picker.preferredDatePickerStyle = .wheels
}
picker.addTarget(self, action: #selector(dueDateChanged(sender:)), for: .valueChanged)
let size = self.view.frame.size
picker.frame = CGRect(x: 0.0, y: size.height - 200, width: size.width, height: 200)
picker.backgroundColor = UIColor.white
self.datePicker = picker
self.view.addSubview(self.datePicker!)
}
#objc func dueDateChanged(sender:UIDatePicker){
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .none
print("action")
dateFilter.setTitle(dateFormatter.string(from: sender.date), for: .normal)
}

Related

Tapping on Date Picker does not popup Picker view in iOS13

In the app when I tap on the UITextField that should give me a UIDatePicker does not show me UIDatePicker on updating the iPhone to iOS 13. Works fine with iOS 12+ versions.
I am working on latest Xcode 11 and macOS Mojave 10.14.6
This is the code I am using:
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
let dateString: String!
activeTextField = textField
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
if activeTextField == fromDateTextField && fromDateTextField.text != "" {
dateString = fromDateTextField.text
let date = dateFormatter.date(from: dateString!)
datePickerView.setDate(date!, animated: false)
} else if activeTextField == toDateTextField && activeTextField.text != "" {
dateString = toDateTextField.text
let date = dateFormatter.date(from: dateString!)
datePickerView.setDate(date!, animated: false)
}
UIView.animate(withDuration: 0.3) {
self.datePickerContainerView.frame = CGRect(x: 0,
y: UIScreen.main.bounds.size.height - 250,
width: UIScreen.main.bounds.size.width,
height: 250)
}
return false
}
This worked for me :
Initialise : let picker = UIDatePicker()
and call createToolbar function in viewDidLoad
func createToolbar() {
let toolbar = UIToolbar()
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Set Date", style: .done, target: nil, action: #selector(showDate))
toolbar.setItems([doneButton], animated: false)
fromDateTextField.inputAccessoryView = toolbar
fromDateTextField.inputView = picker
toDateTextField.inputAccessoryView = toolbar
toDateTextField.inputView = picker
picker.datePickerMode = .date
}
#objc func showDate() {
let dateFormat = DateFormatter()
dateFormat.dateFormat = "dd-MM-yyyy"
let string = dateFormat.string(from: picker.date)
if fromDateTextField.isFirstResponder {
fromDateTextField.text = string
}
if toDateTextField.isFirstResponder {
toDateTextField.text = string
}
self.view.endEditing(true)
}
Thank you #rmmaddy for the inputs :)
class ViewController: UIViewController {
#IBOutlet weak var dateField: UITextField!
var datePicker :UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
datePicker = UIDatePicker.init(frame: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 200))
datePicker.addTarget(self, action: #selector(self.dateChanged), for: .allEvents)
dateField.inputView = datePicker
let doneButton = UIBarButtonItem.init(title: "Done", style: .done, target: self, action: #selector(self.datePickerDone))
let toolBar = UIToolbar.init(frame: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 44))
toolBar.setItems([UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil), doneButton], animated: true)
dateField.inputAccessoryView = toolBar
}
#objc func datePickerDone() {
dateField.resignFirstResponder()
}
#objc func dateChanged() {
dateField.text = "\(datePicker.date)"
}
}
try this

I want in one textfield it can be show keyboard and datepicker

I want show keyboard when user click the button on the right side and show the datePicker when user click the textField,
#IBAction func doEditBirthDate(_ sender: UITextField) {
if (txfBirthDate.isEditing){
btnPhotoIdCard.isHidden = false
lblPhotoIdCard.isHidden = false
let mDatePicker: UIDatePicker = UIDatePicker()
mDatePicker.datePickerMode = .date
sender.inputView = mDatePicker
mDatePicker.addTarget(self, action: #selector(birthDateChanged(sender:)), for: .valueChanged)
}else {
btnPhotoIdCard.isHidden = true
lblPhotoIdCard.isHidden = true
}
}
#objc func birthDateChanged(sender: UIDatePicker) {
let mDateFormatter = DateFormatter()
mDateFormatter.locale = Locale(identifier: "en_US_POSIX")
mDateFormatter.dateFormat = "dd MMMM yyyy"
self.txfBirthDate.text = mDateFormatter.string(from: sender.date)
}
thats just show date picker but i want add button on the right side text field and if user click it can show keyboard and text it to textfield
I'm sorry for my english
You've to try this
class yourViewController: UIViewController,UITextFieldDelegate
{
var screenHeight = UIScreen.main.bound.height
var screenWidth = UIScreen.main.bound.width
var dateFormatter = DateFormatter()
var doneButton = UIBarButtonItem()
var cancelButton = UIBarButtonItem()
var timeValueLabel = UIBarButtonItem()
var datePicker : UIDatePicker!
var toolBarDtPicker = UIToolbar()
//MARK:- Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
yourTxtField.delegate = self
}
//TextField Editing Begin Function
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool
{
self.hideKeyboard()
textField.inputView = nil
textfieldEding(sender: textField)
return false
}
//To Hide Keyboard
#objc func hideKeyboard()
{
UIApplication.shared.sendAction(#selector(UIApplication.resignFirstResponder), to: nil, from: nil, for: nil)
}
//DatePicker Function
func datePickerView()
{
if ((self.datePicker != nil) && (self.datePicker.superview != nil))
{
datePicker.removeFromSuperview()
}
self.datePicker = UIDatePicker(frame: CGRect(x: 0, y:
UIScreen.main.bounds.height-200, width: UIScreen.main.bounds.width, height: 200))
self.datePicker.backgroundColor = UIColor.white
self.datePicker.addTarget(self, action: #selector(dateHandler), for: .valueChanged)
self.view.addSubview(datePicker)
toolBarDtPicker = UIToolbar(frame: CGRect(x: 0, y: screenHeight-230, width: screenWidth, height: 30))
toolBarDtPicker.barStyle = .default
toolBarDtPicker.isTranslucent = false
toolBarDtPicker.barTintColor = UIColor.blue
toolBarDtPicker.sizeToFit()
// Adding Button ToolBar
doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneClick))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
timeValueLabel = UIBarButtonItem(title: " ", style: .plain, target: self, action: nil)
let spaceButton2 = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelClick))
doneButton.tintColor = UIColor.white
timeValueLabel.tintColor = UIColor.white
cancelButton.tintColor = UIColor.white
toolBarDtPicker.setItems([cancelButton, spaceButton, timeValueLabel, spaceButton2, doneButton], animated: true)
toolBarDtPicker.isUserInteractionEnabled = true
self.view.addSubview(toolBarDtPicker)
self.toolBarDtPicker.isHidden = false
datePicker.datePickerMode = .date
dateFormatter.dateStyle = .medium
dateFormatter.dateFormat = "EEEE dd MMM yyyy"
}
#objc func textfieldEding(sender: UITextField)
{
datePickerView()
}
#IBAction func showKeyBoard(_ sender: UIButton!)
{
self.yourTxtField.becomeFirstResponder()
}
//MARK: DatePicker
#objc func dateHandler(sender: UIDatePicker)
{
dateFormatter.dateFormat = "EEEE dd MMM yyyy"
timeValueLabel.title = dateFormatter.string(from: sender.date)
}
#objc func doneClick() //DatePIcker Done Button
{
//Done Button Code
}
//MARK: Cancel Btn
#objc func cancelClick() //DatePIcker Cancel Button
{
if ((self.datePicker != nil) && (self.datePicker.superview != nil))
{
datePicker.removeFromSuperview()
}
toolBarDtPicker.removeFromSuperview()
}
}

UIDatePicker as a Inputview to UITextField

In my code i have used Datepicker as a Inputview to Textfield
self.tFPeriodEndCurrent.inputView = self.datePicker
textfield delegates won't work because Textfield is not editable.
i need to update text(date) in textfield to UIPicker input view when ever user clicked on Textfield
//assume textfield contains 20/2/2019 , that should reflect in UIdatepicker when user Tap on textfield.
how to acheive that! any help
Firstly create datePicker programmatically:
private lazy var datePicker: UIDatePicker = {
let datePicker = UIDatePicker(frame: .zero)
datePicker.datePickerMode = .date
datePicker.timeZone = TimeZone.current
return datePicker
}()
In 'viewDidLoad' or 'awakeFromNib':
fieldValueTextField.inputView = datePicker
datePicker.addTarget(self, action: #selector(handleDatePicker(sender:)), for: .valueChanged)
Create the method that will handle editing:
#objc func handleDatePicker(sender: UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMM yyyy"
fieldValueTextField.text = dateFormatter.string(from: sender.date)
}
In Swift 5, Xcode 12 use the following:
if #available(iOS 14, *) {
datePicker.preferredDatePickerStyle = .wheels
}
It will set the picker to the same like in iOS 13.
If you want to bring the same UIPickerView look & feel try this,
class ViewController: UIViewController {
#IBOutlet weak var dateField: UITextField!
var datePicker :UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
datePicker = UIDatePicker.init(frame: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 200))
datePicker.addTarget(self, action: #selector(self.dateChanged), for: .allEvents)
dateField.inputView = datePicker
let doneButton = UIBarButtonItem.init(title: "Done", style: .done, target: self, action: #selector(self.datePickerDone))
let toolBar = UIToolbar.init(frame: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 44))
toolBar.setItems([UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil), doneButton], animated: true)
dateField.inputAccessoryView = toolBar
}
#objc func datePickerDone() {
dateField.resignFirstResponder()
}
#objc func dateChanged() {
dateField.text = "\(datePicker.date)"
}
}
class ViewController: UIViewController {
#IBOutlet weak var txtDatePicker: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let datePickerView = UIDatePicker()
datePickerView.datePickerMode = .date
txtDatePicker.inputView = datePickerView
datePickerView.addTarget(self, action: #selector(handleDatePicker(sender:)), for: .valueChanged)
}
#objc func handleDatePicker(sender: UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMM yyyy"
txtDatePicker.text = dateFormatter.string(from: sender.date)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
First you need to convert the string into date.
Assume textfield contains "20/2/2019"
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"dd/M/yyyy";
NSDate *dt = [formatter dateFromString:self.textField.text];
You also need to implement UITextFieldDelegate method
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if (self.tFPeriodEndCurrent == textField) {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"dd/M/yyyy";
NSDate *dt = [formatter dateFromString:textField.text];
if (textField.inputView isKindOfClass:[UIDatePicker class]) {
UIDatePicker *dtPicker = (UIDatePicker *)textField.inputView;
[dtPicker setDate:dt];
}
}
return TRUE;
}
Don't forget to set the textfield delegate.
Swift version
var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
return formatter
}()
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
guard let txtDate = textField.text else { return true }
if textField == tFPeriodEndCurrent, let dt = dateFormatter.date(from: txtDate) {
if let datePicker = textField.inputView as? UIDatePicker {
datePicker.setDate(dt, animated: true)
}
}
return true
}

Using datePicker for multiple textfields in iOS swift

I am having 4 textFields where I have to set fromDate, fromTime and toDate, toTime for a userServiceBooking. Now, I need to fill these textFields with UIDatePicker and I am not able to show the text and I don't know why; maybe I am doing it totally wrong...
I am posting the code that I've tried and please someone look into it and tell how to do it.
Code:
import UIKit
class ConfirmRequestViewController: UIViewController,UITextFieldDelegate {
#IBOutlet weak var fromDateTF: UITextField!
#IBOutlet weak var toDateTF: UITextField!
#IBOutlet weak var fromTimeTF: UITextField!
#IBOutlet weak var toTimeTF: UITextField!
var datePicker = UIDatePicker()
var dateFormatter = DateFormatter()
var toolBar = UIToolbar()
override func viewDidLoad() {
super.viewDidLoad()
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == fromDateTF {
datePicker.datePickerMode = .date
fromDateTF.inputView = datePicker
fromDateTF.text = dateFormatter.string(from: datePicker.date)
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonTapped))
toolBar.setItems([doneButton], animated: true)
fromDateTF.inputAccessoryView = toolBar
}
if textField == toDateTF {
datePicker.datePickerMode = .date
toDateTF.inputView = datePicker
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonTapped))
toolBar.setItems([doneButton], animated: true)
toDateTF.inputAccessoryView = toolBar
}
if textField == fromTimeTF {
datePicker.datePickerMode = .time
fromTimeTF.inputView = datePicker
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonTapped))
toolBar.setItems([doneButton], animated: true)
fromTimeTF.inputAccessoryView = toolBar
}
if textField == toTimeTF {
datePicker.datePickerMode = .time
toTimeTF.inputView = datePicker
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonTapped))
toolBar.setItems([doneButton], animated: true)
toTimeTF.inputAccessoryView = toolBar
}
}
#objc func doneButtonTapped(textField: UITextField) {
if textField == fromDateTF {
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
fromDateTF.text = dateFormatter.string(from: datePicker.date)
}
if textField == toDateTF {
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
toDateTF.text = dateFormatter.string(from: datePicker.date)
}
if textField == fromTimeTF {
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .medium
fromTimeTF.text = dateFormatter.string(from: datePicker.date)
}
if textField == toTimeTF {
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .medium
toTimeTF.text = dateFormatter.string(from: datePicker.date)
}
self.view.endEditing(true)
}
}
Try this.
override func viewDidLoad() {
super.viewDidLoad()
fromDateTF.inputView = datePicker
toDateTF.inputView = datePicker
fromTimeTF.inputView = datePicker
toTimeTF.inputView = datePicker
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonTapped))
toolBar.setItems([doneButton], animated: true)
fromDateTF.inputAccessoryView = toolBar
toDateTF.inputAccessoryView = toolBar
fromTimeTF.inputAccessoryView = toolBar
toTimeTF.inputAccessoryView = toolBar
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == fromDateTF {
datePicker.datePickerMode = .date
}
if textField == toDateTF {
datePicker.datePickerMode = .date
}
if textField == fromTimeTF {
datePicker.datePickerMode = .time
}
if textField == toTimeTF {
datePicker.datePickerMode = .time
}
}
#objc func doneButtonTapped() {
if fromDateTF.isFirstResponder {
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
fromDateTF.text = dateFormatter.string(from: datePicker.date)
}
if toDateTF.isFirstResponder {
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
toDateTF.text = dateFormatter.string(from: datePicker.date)
}
if fromTimeTF.isFirstResponder {
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .medium
fromTimeTF.text = dateFormatter.string(from: datePicker.date)
}
if toTimeTF.isFirstResponder {
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .medium
toTimeTF.text = dateFormatter.string(from: datePicker.date)
}
self.view.endEditing(true)
}

Swift passing parameter on #selector

How can I use the same function to handle DatePickerView on 2 different textFields?
To avoid repetition, I would like to set up 2 textFields with a DatePicker. One field is for issue date and the other one for due date.
When I try to add parameter on #objc func doneClick, I got a compiler error ==> Instance member 'doneClick' cannot be used on type 'InvoiceViewController'; did you mean to use a value of this type instead?
import UIKit
class InvoiceViewController: UIViewController, UITextFieldDelegate{
var thePicker = UIDatePicker()
#IBOutlet weak var dateIssueTextField: UITextField!
#IBOutlet weak var dueDateTextField: UITextField!
#objc func doneClick(textField: UITextField!) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .none
dateIssueTextField.text = dateFormatter.string(from: thePicker.date)
dateFormatter.dateFormat = "yyyy"
let year: String = dateFormatter.string(from: self.thePicker.date)
dateFormatter.dateFormat = "MM"
let month: String = dateFormatter.string(from: self.thePicker.date)
dateFormatter.dateFormat = "dd"
let day: String = dateFormatter.string(from: self.thePicker.date)
let finalDate = year+"-"+month+"-"+day
print(finalDate)
// dateIssueTextField.resignFirstResponder()
textField.resignFirstResponder()
}
#objc func cancelClick() {
dateIssueTextField.resignFirstResponder()
}
func setUpTextFieldPicker(textField: UITextField) {
// DatePicker
self.thePicker = UIDatePicker(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
self.thePicker.backgroundColor = UIColor.white
self.thePicker.datePickerMode = UIDatePickerMode.date
// dateIssueTextField.inputView = thePicker
// dueDateTextField.inputView = thePicker
textField.inputView = thePicker
// ToolBar
let toolBar = UIToolbar()
toolBar.barStyle = .default
toolBar.isTranslucent = true
toolBar.tintColor = UIColor(red: 92/255, green: 216/255, blue: 255/255, alpha: 1)
toolBar.sizeToFit()
// Adding Button ToolBar
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(InvoiceViewController.doneClick))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(InvoiceViewController.cancelClick))
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
//dateIssueTextField.inputAccessoryView = toolBar
//dueDateTextField.inputAccessoryView = toolBar
textField.inputAccessoryView = toolBar
}
override func viewDidLoad() {
super.viewDidLoad()
setUpTextFieldPicker(textField: dateIssueTextField)
setUpTextFieldPicker(textField: dueDateTextField)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
doneClick cannot have parameter of UITextField type, when it's used as a target to UIBarButtonItem.
You will have to edit more than just that method. The toolbar needs to know to which UITextField it belongs to. So create your custom subclass of UIToolbar, in which you will setup its items, and add a delegate to it which will be sent events on done and cancel pressed:
import UIKit
protocol AccessoryToolbarDelegate: class {
func doneClicked(for textField: UITextField)
func cancelClicked(for textField: UITextField)
}
class AccessoryToolbar: UIToolbar {
fileprivate let textField: UITextField
weak var accessoryDelegate: AccessoryToolbarDelegate?
init(for textField: UITextField) {
self.textField = textField
super.init(frame: CGRect.zero)
self.barStyle = .default
self.isTranslucent = true
self.tintColor = UIColor(red: 92/255, green: 216/255, blue: 255/255, alpha: 1)
self.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneClicked))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelClicked))
self.setItems([cancelButton, spaceButton, doneButton], animated: false)
self.isUserInteractionEnabled = true
textField.inputAccessoryView = self
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
#objc fileprivate func doneClicked() {
accessoryDelegate?.doneClicked(for: self.textField)
}
#objc fileprivate func cancelClicked() {
accessoryDelegate?.cancelClicked(for: self.textField)
}
}
Now with this code you can rewrite your old code to:
import UIKit
class InvoiceViewController: UIViewController, AccessoryToolbarDelegate {
var thePicker = UIDatePicker()
#IBOutlet weak var dateIssueTextField: UITextField!
#IBOutlet weak var dueDateTextField: UITextField!
func doneClicked(for textField: UITextField) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .none
// I am not sure if you want this
textField.text = dateFormatter.string(from: thePicker.date)
// or rather this, but that's up to you to finish
dateFormatter.dateFormat = "yyyy-MM-dd"
let finalDate: String = dateFormatter.string(from: thePicker.date)
print(finalDate)
textField.resignFirstResponder()
}
func cancelClicked(for textField: UITextField) {
textField.resignFirstResponder()
}
func setUpTextFieldPicker(textField: UITextField) {
// DatePicker
self.thePicker = UIDatePicker(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
self.thePicker.backgroundColor = UIColor.white
self.thePicker.datePickerMode = UIDatePickerMode.date
// dateIssueTextField.inputView = thePicker
// dueDateTextField.inputView = thePicker
textField.inputView = thePicker
// ToolBar
let toolbar = AccessoryToolbar(for: textField)
// let's not forget to set the delegate
toolbar.accessoryDelegate = self
}
override func viewDidLoad() {
super.viewDidLoad()
setUpTextFieldPicker(textField: dateIssueTextField)
setUpTextFieldPicker(textField: dueDateTextField)
}
}

Resources