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()
}
}
Related
I need to add DatePicker to three textfields for that
I have created one datepicker like below
func addInputViewDatePicker(target: Any, selector: Selector) {
let screenWidth = UIScreen.main.bounds.width
//Add DatePicker as inputView
let datePicker = UIDatePicker(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 216))
datePicker.datePickerMode = .date
self.inputView = datePicker
//Add Tool Bar as input AccessoryView
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 44))
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelBarButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelPressed))
let doneBarButton = UIBarButtonItem(title: "Done", style: .plain, target: target, action: selector)
toolBar.setItems([cancelBarButton, flexibleSpace, doneBarButton], animated: false)
self.inputAccessoryView = toolBar
}
#objc func cancelPressed() {
self.resignFirstResponder()
}
and i am adding datepicker to three textfields in doneButtonPressed like below
#objc func doneButtonPressed() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
if let datePicker = self.fromDateTextfield.inputView as? UIDatePicker {
self.fromDateTextfield.text = dateFormatter.string(from: datePicker.date)
}
if let datePicker = self.toDateTextfield.inputView as? UIDatePicker {
self.toDateTextfield.text = dateFormatter.string(from: datePicker.date)
}
if let datePicker = self.lastbidDateTextfield.inputView as? UIDatePicker {
self.lastbidDateTextfield.text = dateFormatter.string(from: datePicker.date)
}
self.lastbidDateTextfield.resignFirstResponder()
self.toDateTextfield.resignFirstResponder()
self.fromDateTextfield.resignFirstResponder()
}
and in viewdidload:
override func viewDidLoad() {
super.viewDidLoad()
fromDateTextfield.addInputViewDatePicker(target: self, selector: #selector(doneButtonPressed))
toDateTextfield.addInputViewDatePicker(target: self, selector: #selector(doneButtonPressed))
lastbidDateTextfield.addInputViewDatePicker(target: self, selector: #selector(doneButtonPressed))
}
with above code if i add date in fromDateTextfield then in all three textfields same date is adding.. without going to that remaining two textfields
i want to add different dates to three textfields.. how to do that with above code..
if my above code is wrong please help me with new correct working code for three three textfields
Set a tag to every UIBarButtonItem from 0 to 2
func addInputViewDatePicker(target: Any, selector: Selector,tag:Int)
.....
doneBarButton.tag = tag
}
#objc func doneButtonPressed(_ sender: UIBarButtonItem) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let arr = [fromDateTextfield,toDateTextfield,lastbidDateTextfield]
let current = arr[sender.tag]
if let datePicker = current.inputView as? UIDatePicker {
current.text = dateFormatter.string(from: datePicker.date)
current.resignFirstResponder()
}
}
I try to use this code to get date picker when clicking on a text field:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var DOBTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
DOBTextField.addInputViewDatePicker(target: self, selector: #selector(doneButtonPressed))
}
#objc func doneButtonPressed() {
if let datePicker = self.DOBTextField.inputView as? UIDatePicker {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .short
dateFormatter.locale = Locale.init(identifier: "it_IT")
self.DOBTextField.text = dateFormatter.string(from: datePicker.date)
}
self.DOBTextField.resignFirstResponder()
}
}
extension UITextField {
func addInputViewDatePicker(target: Any, selector: Selector) {
let screenWidth = UIScreen.main.bounds.width
//Add DatePicker as inputView
let datePicker = UIDatePicker(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 216))
datePicker.datePickerMode = .time
datePicker.locale = Locale.init(identifier: "it_IT")
self.inputView = datePicker
//Add Tool Bar as input AccessoryView
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 44))
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelBarButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelPressed))
let doneBarButton = UIBarButtonItem(title: "Done", style: .plain, target: target, action: selector)
toolBar.setItems([cancelBarButton, flexibleSpace, doneBarButton], animated: false)
self.inputAccessoryView = toolBar
}
#objc func cancelPressed() {
self.resignFirstResponder()
}
}
But when I click on text field again, time on date picker move forward on 3 dimensions. How this can be fixed? I want time on date picker to rest the same as it is on text field.
I try to implement this code, but it crash:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var DOBTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
DOBTextField.addInputViewDatePicker(target: self, selector: #selector(doneButtonPressed), textFieldText: DOBTextField.text ?? "")
}
#objc func doneButtonPressed() {
if let datePicker = self.DOBTextField.inputView as? UIDatePicker {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .short
dateFormatter.locale = Locale.init(identifier: "it_IT")
self.DOBTextField.text = dateFormatter.string(from: datePicker.date)
}
self.DOBTextField.resignFirstResponder()
}
}
extension UITextField {
func addInputViewDatePicker(target: Any, selector: Selector , textFieldText: String?) {
let screenWidth = UIScreen.main.bounds.width
//Add DatePicker as inputView
let datePicker = UIDatePicker(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 216))
datePicker.datePickerMode = .time
datePicker.locale = Locale.init(identifier: "it_IT")
self.inputView = datePicker
if textFieldText != nil {
/// Set Textfield date & time
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .short
dateFormatter.locale = Locale.init(identifier: "it_IT")
datePicker.date = dateFormatter.date(from: textFieldText!)!
}
else {
/// set current date & time
datePicker.date = Date()
}
//Add Tool Bar as input AccessoryView
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 44))
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelBarButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelPressed))
let doneBarButton = UIBarButtonItem(title: "Done", style: .plain, target: target, action: selector)
toolBar.setItems([cancelBarButton, flexibleSpace, doneBarButton], animated: false)
self.inputAccessoryView = toolBar
}
#objc func cancelPressed() {
self.resignFirstResponder()
}
}
How this can be fixed?
As per I understand, You want to textfield's time when datepicker opens. You just have to set date for DatePicker when it will be initialized.
Set DatePicker's date :
extension UITextField {
func addInputViewDatePicker(target: Any, selector: Selector , textFieldText:String?) {
//Add DatePicker as inputView
//Set date for date Picker
if textFieldText != nil {
/// Set Textfield date & time
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .short
dateFormatter.locale = Locale.init(identifier: "it_IT")
datePicker.date = dateFormatter.date(from: textFieldText!)!
}
else {
/// set current date & time
datePicker.date = Date()
}
//Add Tool Bar as input AccessoryView
}
}
Change in your viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
DOBTextField.addInputViewDatePicker(target: self, selector: #selector(doneButtonPressed), textFieldText: DOBTextField.text ?? "")
}
I hope you understand what you have to set with datepicker. If this code is not working as you want then take Action of textfield (Editing Did Begin) & try to set textfield inputView in Action.
It seems this problem only appears on simulators. When I try to test this code on real device everything works fine. May be it's just Xcode bug.
I try to get string from textfield, then convert it to date and put this value in datepicker. But for some reason it fails everytime and I get: "There is issue in dateformatter. Not able to convert string to Date".
I don't understand what I'm doing wrong and how I get this works.
My code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var DOBTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
DOBTextField.addInputViewDatePicker(target: self, selector: #selector(doneButtonPressed), textFieldText: DOBTextField.text)
}
#objc func doneButtonPressed() {
if let datePicker = self.DOBTextField.inputView as? UIDatePicker {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .none
self.DOBTextField.text = dateFormatter.string(from: datePicker.date)
}
self.DOBTextField.resignFirstResponder()
}
}
extension UITextField {
func addInputViewDatePicker(target: Any, selector: Selector , textFieldText: String?) {
let screenWidth = UIScreen.main.bounds.width
let datePicker = UIDatePicker(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 216))
datePicker.datePickerMode = .date
self.inputView = datePicker
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .none
if textFieldText != nil {
if let date = dateFormatter.date(from: textFieldText!) {
datePicker.date = date
} else {
print("There is issue in dateformatter. Not able to convert string to Date ")
}
}
else {
datePicker.date = Date()
}
//Add Tool Bar as input AccessoryView
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 44))
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelBarButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelPressed))
let doneBarButton = UIBarButtonItem(title: "Done", style: .plain, target: target, action: selector)
toolBar.setItems([cancelBarButton, flexibleSpace, doneBarButton], animated: false)
self.inputAccessoryView = toolBar
}
#objc func cancelPressed() {
self.resignFirstResponder()
}
}
I don't understand what I'm doing wrong and why this code doesn't work. May be someone can help me resolve this issue?
As I see when you call addInputViewDatePicker on viewDidLoad, the value of textFieldText is "" that's why you see your print from start
you can try use this code (but, I guess, you can optimize it):
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var DOBTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
prepareDOBTextField()
DOBTextField.addInputViewDatePicker(target: self, selector: #selector(doneButtonPressed), textFieldText: DOBTextField.text)
}
#objc func doneButtonPressed() {
if let datePicker = self.DOBTextField.inputView as? UIDatePicker {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .none
self.DOBTextField.text = dateFormatter.string(from: datePicker.date)
}
self.DOBTextField.resignFirstResponder()
}
func prepareDOBTextField() {
let date = Date()
let formatter = DateFormatter()
formatter.dateStyle = .long
formatter.timeStyle = .none
let result = formatter.string(from: date)
self.DOBTextField.text = result
}
}
extension UITextField {
func addInputViewDatePicker(target: Any, selector: Selector , textFieldText: String?) {
let screenWidth = UIScreen.main.bounds.width
let datePicker = UIDatePicker(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 216))
datePicker.datePickerMode = .date
self.inputView = datePicker
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .none
if textFieldText != nil && textFieldText != "" {
if let date = dateFormatter.date(from: textFieldText!) {
datePicker.date = date
} else {
print("There is issue in dateformatter. Not able to convert string to Date ")
}
}
else {
datePicker.date = Date()
}
//Add Tool Bar as input AccessoryView
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 44))
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelBarButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelPressed))
let doneBarButton = UIBarButtonItem(title: "Done", style: .plain, target: target, action: selector)
toolBar.setItems([cancelBarButton, flexibleSpace, doneBarButton], animated: false)
self.inputAccessoryView = toolBar
}
#objc func cancelPressed() {
self.resignFirstResponder()
}
}
You can do this by follow my code below.
#objc func doneButtonPressed() {
//Converting string to date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
let date = dateFormatter.date(from: DOBTextField.text!)
//Sets the date in the date picker
datepicker.setDate(date!, animated: true)
}
So first you're converting your textfield (DOBTextField.text) into Date.
Right after you're setting the datePicker to be the correct date.
In this case you will have to enter exactly like this in the textfield:
"2019-12-18 14:50"
Solved this question. I get rid of extenstion and write code for datepicker in ViewController.
import UIKit
class ViewController: UIViewController {
#IBOutlet var textField: UITextField!
let datePicker = UIDatePicker()
override func viewDidLoad() {
super.viewDidLoad()
createDatePicker()
}
func createDatePicker() {
textField.inputView = datePicker
datePicker.datePickerMode = .date
datePicker.maximumDate = Date()
let toolbar = UIToolbar()
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(doneClicked))
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
toolbar.setItems([flexibleSpace, doneButton], animated: true)
textField.inputAccessoryView = toolbar
}
#objc func doneClicked() {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .none
textField.text = dateFormatter.string(from: datePicker.date)
self.view.endEditing(true)
}
}
After I added to viewWillAppear actual values of datepicker:
override func viewWillAppear(_ animated: Bool) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .none
datePicker.date = dateFormatter.date(from: textfield.text!)!
}
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
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)
}
}