UIDatepicker toolbar not working in landscape mode in ios swift - ios

Application working on both landscape and portrait. Using UIDatepicker to pick the date. Here UIDatepicker code.
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)
}
}
UIDatePicker toolbar working fine in portrait mode.
change the app in landscape mode the toolbar get hide.
How to fix this issue help.
Google it and refer some link:
Add a Done button within a pop-up datePickerView in Swift?
It will not workout to me. Help me to fix this issue.

I think you need to set the frame for datepicker.
self.datePicker = UIDatePicker(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))

That seems like a bug in iOS 11 and which is not appearing in iOS 12. Please refer this in apple developer forums.
https://forums.developer.apple.com/thread/81650
Fix:
func textFieldDidBeginEditing(_ textField: UITextField) {
let item = textField.inputAssistantItem
item.leadingBarButtonGroups = []
item.trailingBarButtonGroups = []
//Your code here....
}
Also please have a look at this link once
Custom Keyboard InputAccessoryView not visible in iOS 11

Related

How to achieve the custom picker with Month, Date and time in iOS swift?

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.

Rx swift - Date picker freezes Rx swift View controller

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

Toolbar button in UIDatePicker shows only after double click on TextField

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.

iOS Swift 3 - UIDatePicker

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

How to bring up a date picker when a date field is tapped?

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.

Resources