I wanna let user to set time in UIDatePicker which shows after click on UITextField, but Toolbar with done button shows only when user will click twice on UITextField.
func showDatePicker(){
//Formate Date
datepickerView.datePickerMode = .time
//ToolBar
let toolbar = UIToolbar();
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(donedatePicker));
toolbar.setItems([doneButton], animated: false)
workHoursStartTextField.inputAccessoryView = toolbar
}
#objc func doneButtonDatePicker(){
let formatter = DateFormatter()
formatter.dateFormat = "HH:mm"
workHoursStartTextField.text = formatter.string(from: datepickerView.date)
self.view.endEditing(true)
}
#objc func tapOnStartWork(gestureReconizer: UITapGestureRecognizer) {
print("Start work")
datepickerView.isHidden = false
showDatePicker()
}
and calling method
override func viewDidLoad() {
super.viewDidLoad()
let tapStartWork = UITapGestureRecognizer(target: self, action: #selector(tapOnStartWork(gestureReconizer:)))
workHoursStartTextField.addGestureRecognizer(tapStartWork)
}
When I click on UITextField text "Start work" prints in console, but toolbar button is still hide.
Related
I am developing an app which requires to select the date from a picker view. But the picker view requires the Month,Date and time in the Picker view rows like in the attached image:
currently i am having the following code :
class ViewController: UIViewController {
#IBOutlet weak var txtDatePicker: UITextField!
let datePicker = UIDatePicker()
override func viewDidLoad() {
super.viewDidLoad()
showDatePicker()
}
func showDatePicker(){
//Formate Date
datePicker.datePickerMode = .date
//ToolBar
let toolbar = UIToolbar();
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(donedatePicker));
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelDatePicker));
toolbar.setItems([doneButton,spaceButton,cancelButton], animated: false)
txtDatePicker.inputAccessoryView = toolbar
txtDatePicker.inputView = datePicker
}
#objc func donedatePicker(){
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
txtDatePicker.text = formatter.string(from: datePicker.date)
self.view.endEditing(true)
}
#objc func cancelDatePicker(){
self.view.endEditing(true)
}
}
But with this i am getting the output as :
How to add time to the UIPickerView ? Please suggest and help
Go to storyboard select your date picker view and in attribute inspector select date and time instead of Date.
And then you can select the date and time for the date picker.
Here is code i am using, i am new to rxswift. My question is simple when i tap on textfield date picker opens and it freezes my ViewController. I don't know what is the problem with UI in rxswift, this works well in only swift project. Your help is appreaciated pls help.
class ViewController: UIViewController {
//Text Field Connection
#IBOutlet weak var txtDatePicker: UITextField!
//Uidate picker
let datePicker = UIDatePicker()
override func viewDidLoad() {
super.viewDidLoad()
//show date picker
showDatePicker()
}
func showDatePicker(){
//Formate Date
datePicker.datePickerMode = .date
//ToolBar
let toolbar = UIToolbar();
toolbar.sizeToFit()
//done button & cancel button
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.bordered, target: self, action: "donedatePicker")
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.bordered, target: self, action: "cancelDatePicker")
toolbar.setItems([doneButton,spaceButton,cancelButton], animated: false)
// add toolbar to textField
txtDatePicker.inputAccessoryView = toolbar
// add datepicker to textField
txtDatePicker.inputView = datePicker
}
func donedatePicker(){
//For date formate
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
txtDatePicker.text = formatter.string(from: datePicker.date)
//dismiss date picker dialog
self.view.endEditing(true)
}
func cancelDatePicker(){
//cancel button dismiss datepicker dialog
self.view.endEditing(true)
}
}
a
I want show a date picker view on keyboard. I am doing this using UITextField extension.
My code:
extension UITextField {
//... other functions
func showDatePicker(){
let datePicker = UIDatePicker()
datePicker.datePickerMode = .date
let toolbar = UIToolbar();
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Pronto", style: UIBarButtonItemStyle.plain, target: self, action: #selector(UITextField.doneDatePicker(_:)))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancelar", style: UIBarButtonItemStyle.plain, target: self, action: #selector(UITextField.donePicker))
toolbar.setItems([cancelButton,spaceButton,doneButton], animated: false)
self.inputAccessoryView = toolbar
self.inputView = datePicker
}
#objc func doneDatePicker(_ datePicker: UIDatePicker){
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
self.text = formatter.string(from: datePicker.date)
self.endEditing(true)
}
}
My problem is when I tap "Pronto" button and the function doneDatePicker is executed. I need pass the UIDatePicker (or just the date) to show the date on textfield but I get this error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIBarButtonItem date]: unrecognized selector sent to instance 0x103488850'
How can I solve this?
You should simply subclass UITextField and declare your datepicker as a property of your UITextField, override didMoveToSuperview method and do the customisation there:
class DateField: UITextField {
var date: Date?
let datePicker = UIDatePicker()
let formatter = DateFormatter()
override func didMoveToSuperview() {
datePicker.datePickerMode = .date
formatter.dateStyle = .short
let toolbar = UIToolbar()
toolbar.sizeToFit()
let done = UIBarButtonItem(title: "Pronto", style: .plain, target: self, action: #selector(doneAction))
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancel = UIBarButtonItem(title: "Cancelar", style: .plain, target: self, action: #selector(cancelAction))
toolbar.setItems([cancel,space,done], animated: false)
inputAccessoryView = toolbar
inputView = datePicker
}
#objc func cancelAction(_ sender: UIBarButtonItem) {
endEditing(true)
}
#objc func doneAction(_ sender: UIBarButtonItem) {
date = datePicker.date
text = formatter.string(from: datePicker.date)
endEditing(true)
}
}
It is not possible to pass extra parameters through selectors. Why you are passing date picker to
#objc func doneDatePicker(_ datePicker: UIDatePicker)
Replace
let datePicker = UIDatePicker()
with
var datePicker: UIDatePicker!
and put it as shared instance in a singleton class.
then access datePicker inside the function.
I have a UIDatePicker that shows the day, month and the year. But I don't know how to get those parameters.
So What is the best way to get the day, month and year from UIDatePicker using Swift 3?
UIDatePicker in Swift 3 and Swift 4 example.
In Swift 3 You can use
Create Simple Project of Single View Application in swift 3
Drag a text field & connect to viewController
Date picker look like image
ViewController code is bellow..
class ViewController: UIViewController {
//Text Field Connection
#IBOutlet weak var txtDatePicker: UITextField!
//Uidate picker
let datePicker = UIDatePicker()
override func viewDidLoad() {
super.viewDidLoad()
//show date picker
showDatePicker()
}
func showDatePicker(){
//Formate Date
datePicker.datePickerMode = .date
//ToolBar
let toolbar = UIToolbar();
toolbar.sizeToFit()
//done button & cancel button
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.bordered, target: self, action: "donedatePicker")
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.bordered, target: self, action: "cancelDatePicker")
toolbar.setItems([doneButton,spaceButton,cancelButton], animated: false)
// add toolbar to textField
txtDatePicker.inputAccessoryView = toolbar
// add datepicker to textField
txtDatePicker.inputView = datePicker
}
func donedatePicker(){
//For date formate
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
txtDatePicker.text = formatter.string(from: datePicker.date)
//dismiss date picker dialog
self.view.endEditing(true)
}
func cancelDatePicker(){
//cancel button dismiss datepicker dialog
self.view.endEditing(true)
}
}
Full Source project is given to github. github Link:https://github.com/enamul95/DatePicker1
In Swift 4 or 5 you can use bellow code
class ViewController: UIViewController {
#IBOutlet weak var txtDatePicker: UITextField!
let datePicker = UIDatePicker()
override func viewDidLoad() {
super.viewDidLoad()
showDatePicker()
}
func showDatePicker(){
//Formate Date
datePicker.datePickerMode = .date
//ToolBar
let toolbar = UIToolbar();
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(donedatePicker));
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelDatePicker));
toolbar.setItems([doneButton,spaceButton,cancelButton], animated: false)
txtDatePicker.inputAccessoryView = toolbar
txtDatePicker.inputView = datePicker
}
#objc func donedatePicker(){
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
txtDatePicker.text = formatter.string(from: datePicker.date)
self.view.endEditing(true)
}
#objc func cancelDatePicker(){
self.view.endEditing(true)
}
}
In Swift 3 you can use DateComponents for that like this way.
First add action on datepicker for .valueChanged events.
datepicker.addTarget(self, action: #selector(dateChanged(_:)), for: .valueChanged)
Then get selected day, month and year using DateComponents in the action.
func dateChanged(_ sender: UIDatePicker) {
let components = Calendar.current.dateComponents([.year, .month, .day], from: sender.date)
if let day = components.day, let month = components.month, let year = components.year {
print("\(day) \(month) \(year)")
}
}
Suppose if you want to show datePicker on tapping textfield and when user select some date from it then it will automatically populate on your textfield .
#IBOutlet weak var dateTextField: UITextField!
let datePickerView:UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.date
dateTextField.inputView = datePickerView
datePickerView.addTarget(self, action: #selector(ViewController.datePickerValueChanged), for: UIControlEvents.valueChanged)
// Make a dateFormatter in which format you would like to display the selected date in the textfield.
func datePickerValueChanged(sender:UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = DateFormatter.Style.medium
dateFormatter.timeStyle = DateFormatter.Style.none
dateTextField.text = dateFormatter.string(from: sender.date)
}
Here Sender.date which is the instance of UIDatePicker pick up the date from the datepicker and populate on your textfield.
Create IBOutlet of UIDatePicker and connect it properly then use below code to get day, month, year ect.
var comp = NSDateComponents()
#IBOutlet weak var datePicker: UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
datePicker.addTarget(self, action: Selector("datePickerChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}
func datePickerChanged(datePicker:UIDatePicker){
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
let cal = NSCalendar.currentCalendar()
comp = cal.components([.Era, .Day, .Month, .Year, .Hour, .Minute] , fromDate: datePicker.date)
// getting day, month, year ect
print ("Era:\(comp.era) Date:\(comp.day) Month:\(comp.month) Month:\(comp.year) Hours: \(comp.hour) Minuts:\(comp.minute)")
}
var picker = UIDatePicker()
picker = UIDatePicker()
textField.inputView = picker
picker.addTarget(self, action: #selector(ViewController.handleDatePicker), for: UIControlEvents.valueChanged)
picker.datePickerMode = .date
func handleDatePicker() {
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
textfield.text = dateFormatter.string(from: picker.date)
textfield.resignFirstResponder()
}
Swift 5 users can try this it works for me
import UIKit
class FreeCallsViewController: UIViewController {
#IBOutlet weak var dateTextField: UITextField!
let datepicker = UIDatePicker()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func calenderButtonPressed(_ sender: UIButton) {
self.createDatePicker()
}
func createDatePicker() {
let toolbar = UIToolbar()
toolbar.sizeToFit()
let donebtn = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donepressed))
toolbar.setItems([donebtn], animated: true)
dateTextField.inputAccessoryView = toolbar
dateTextField.inputView = datepicker
datepicker.datePickerMode = .date
}
#objc func donepressed() {
let dateformator = DateFormatter()
dateformator.dateStyle = .medium
dateformator.timeStyle = .none
dateTextField.text = dateformator.string(from: datepicker.date)
self.view.endEditing(true)
}
}
The problem can be solved in numerous way. If you are looking for a solution only using code:
class Foo: UIViewController {
// Lets create your picker - Can be IBOutlet too
lazy var datePicker: UIDatePicker = {
let picker = UIDatePicker()
picker.datePickerMode = .date
return picker
}()
override func viewDidLoad() {
super.viewDidLoad()
//Observe the value changes in datePickerValueChanged function for example
datePicker.addTarget(self, action: #selector(datePickerValueChanged), for: .valueChanged)
}
func datePickerValueChanged(sender: UIDatePicker) {
// Function will be called every time picker changes it's value
// You can access to it the following way
print(sender.date)
}
}
The other way if you have your UIDatePicker in Interface Builder. You pretty much need to the same thing, like above, but i a slightly different way. Click on your UIDatePicker in Interface Builder:
You see the Value Changed option at the buttom. Now you grab and drag an IBAction to your viewController, and set up your connection like this:
This way you achive the same as the first example, because you end up with pretty much the same function:
#IBAction func datePickerValueChanged(sender: UIDatePicker) {
print(sender.date)
}
Swift 5.0+
I hope it will work for you, Enjoy!
import UIKit
protocol SKUIDatePickerDelegate:class {
func getDate(_ sKUIDatePicker:SKUIDatePicker, date:String)
func cancel(_ sKUIDatePicker:SKUIDatePicker)
}
class SKUIDatePicker:UIView {
private let datePicker = UIDatePicker()
private var dateFormate = "yyyy/mm/dd"
weak var delegate:SKUIDatePickerDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
// self.frame = UIScreen.main.bounds
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func showDatePicker(txtDatePicker:UITextField){
//Formate Date
datePicker.datePickerMode = .date
//ToolBar
let toolbar = UIToolbar();
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(donedatePicker));
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelDatePicker));
toolbar.setItems([doneButton,spaceButton,cancelButton], animated: false)
txtDatePicker.inputAccessoryView = toolbar
txtDatePicker.inputView = datePicker
}
#objc func donedatePicker(){
let formatter = DateFormatter()
formatter.dateFormat = dateFormate
let result = formatter.string(from: datePicker.date)
self.delegate?.getDate(self, date: result)
}
#objc func cancelDatePicker(){
self.delegate?.cancel(self)
}
}
Usage
class ViewController: UIViewController,SKUIDatePickerDelegate {
//Text Field Connection
#IBOutlet weak var txtDatePicker: UITextField!
private var skUIdatePicker:SKUIdatePicker?
override func viewDidLoad() {
super.viewDidLoad()
skUIdatePicker = SKUIdatePicker()
skUIdatePicker.delegate = self
skUIdatePicker.showDatePicker(txtDatePicker:txtDatePicker)
}
func getDate(_ sKUIDatePicker:SKUIDatePicker, date:String) {
print(date)
self.view.endEditing(true)
}
func cancel(_ sKUIDatePicker:SKUIDatePicker){
self.view.endEditing(true)
}
}
I have a view with a text field for date. I want the current date to default to "today" but if the user wants to put in a different date, he can tap the field to bring up a date picker (already added to the view). I found a similar question and answer that I though was going to work. I have no errors but when I tap on the date field the keyboard comes up, not the date picker.
#IBOutlet var enterDate: UITextField!
#IBAction func dateTapped(sender: UITextField) {
//code for what to do when date field is tapped
var datePickerView : UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.Date
sender.inputView = datePickerView
datePickerView.addTarget(self, action: Selector("handleDatePicker:"), forControlEvents: UIControlEvents.ValueChanged)
}
func handleDatePicker(sender: UIDatePicker) {
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd MMM yyyy"
enterDate.text = dateFormatter.stringFromDate(sender.date)
}
Create Extension of UITextField and add the following methods.
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 = .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()
}
}
In ViewController Add a UITextField and create IBOutlet:-
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 = .medium
self.DOBTextField.text = dateFormatter.string(from: datePicker.date)
}
self.DOBTextField.resignFirstResponder()
}
}
I guess you are taking a UITextField for the input but you have not established a connection between the datePicker and textfield.
Have a look at this answer here
In swift this can be done by textfield.inputView = datePickerView. After this the click on textfield will be handled by datePicker, but you should initialize datePicker before doing this.
I don't think you need the dateTapped action. If you put all your setup code in a place where you initialize the text field I think it will work automatically.
I think the problem you're seeing is due to you setting the inputView only after the text field is pressed. If you set it before (e.g. enterDate.inputView = datePickerView) the system should handle the rest. In other words, when that text field becomes the first responder it will show the inputView instead of the regular keyboard.