DatePicker passing data - ios

I have a successful date picker and on the following page a stepper/number picker that allows users to select dates, and item quantities. In a new view, I would like to display all the previous information for them to review. I have a few methods in place but they don't seem to work. I am guessing it is because they aren't textFields, and some extra code is needed in order to ask the UIdatepicker and Stepper to pass the information. Take a look below please :)
Here is my date picker View Controller
import UIKit
class StoreDatesViewController: UIViewController {
#IBOutlet weak var nextButton: UIButton!
#IBOutlet weak var dropOff: UITextField!
#IBOutlet weak var pickUp: UITextField!
let datePicker = UIDatePicker()
override func viewDidLoad() {
super.viewDidLoad()
showDatePicker()
}
override func viewWillAppear(_ animated: Bool) {
nextButton.isEnabled = true
}
func showDatePicker(){
//Format Date
datePicker.datePickerMode = .date
datePicker.preferredDatePickerStyle = .inline
datePicker.backgroundColor = UIColor(named: "yellow-2")
//ToolBar
let toolbar = UIToolbar();
toolbar.sizeToFit()
let toolbar2 = UIToolbar();
toolbar2.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(donedatePicker));
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelDatePicker));
let doneButton2 = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(donedatePicker2));
let cancelButton2 = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelDatePicker2));
toolbar.setItems([doneButton,cancelButton], animated: false)
toolbar.tintColor = .white
toolbar.backgroundColor = .red
toolbar2.setItems([doneButton2,cancelButton2], animated: false)
toolbar2.tintColor = .white
dropOff.inputAccessoryView = toolbar
dropOff.inputView = datePicker
pickUp.inputAccessoryView = toolbar2
pickUp.inputView = datePicker
}
#objc func donedatePicker(){
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
dropOff.text = formatter.string(from: datePicker.date)
self.view.endEditing(true)
}
#objc func donedatePicker2(){
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
pickUp.text = formatter.string(from: datePicker.date)
self.view.endEditing(true)
}
#objc func cancelDatePicker(){
self.view.endEditing(true)
}
#objc func cancelDatePicker2(){
self.view.endEditing(true)
}
#IBAction func didTapNext() {
let dropOff = dropOff.text
let pickUp = pickUp.text
let storeDetailsVC = self.storyboard?.instantiateViewController(withIdentifier: "storeDetailsVC") as! storeDetailsViewController
storeDetailsVC.dropOff = dropOff!
storeDetailsVC.pickUp = pickUp!
}
}
Here is my number Pick View Controller
import UIKit
class StoreQuantityViewController: UIViewController{
#IBOutlet weak var numbers: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func stepper(_ sender: UIStepper) {
numbers.text = String(Int(sender.value))
}
#IBAction func next(_ sender: Any) {
let data2 = numbers.text
let storeDetailsVC = self.storyboard?.instantiateViewController(withIdentifier: "storeDetailsVC") as! storeDetailsViewController
storeDetailsVC.data2 = data2!
self.navigationController?.pushViewController(storeDetailsVC, animated: true)
}
}
```

You need to pass the information from text fields to Strings in the next View.
Solution 1:
override func viewDidLoad() {
super.viewDidLoad()
pickUp.text = currentDate // This you can create using the date formatter
dropOff.text = defaultDate // This is default date value you can set if needed
showDatePicker()
}
Solution 2:
#IBAction func didTapNext() {
//Apply validation here to check if its empty if no default value provided.
if dropOff.text.isEmpty {
//Show alert to user to select drof off date.
return
}
if pickUp.text.isEmpty {
//Show alert to user to select PickUp date.
return
}
let dropOff = dropOff.text
let pickUp = pickUp.text
let storeDetailsVC = self.storyboard?.instantiateViewController(withIdentifier: "storeDetailsVC") as! storeDetailsViewController
storeDetailsVC.dropOff = dropOff!
storeDetailsVC.pickUp = pickUp!
}

Related

I can't pass data between classes using callback as completion handler

I want to pass text of textField in custom class to ViewController and populate it to array when BarButtonItem of DatePicker is tapped. I used a callback as completion handler, but it caught EXC-BAD-ACCESS. What made this error and how could I pass text to my ViewController?
Custom class of textField
class HourDatePicker: UITextField {
var datePicker = UIDatePicker()
override init(frame: CGRect) {
super.init(frame: frame)
commominit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commominit()
}
func commominit(){
text = ""
datePicker.datePickerMode = .dateAndTime
datePicker.minuteInterval = 30
datePicker.locale = Locale(identifier: "ja")
datePicker.addTarget(self, action: #selector(setText), for: .valueChanged)
setText()
inputView = datePicker
inputAccessoryView = customPicker()
}
#objc func setText(){
let f = DateFormatter()
f.dateStyle = .full
f.timeStyle = .short
f.locale = Locale(identifier: "ja")
textColor = .black
text = "\(f.string(from: datePicker.date))"
}
private func customPicker() -> UIToolbar {
let toolbar = UIToolbar()
toolbar.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: 40)
let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: self, action: nil)
space.width = 100
let flexSpaceItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
let todayButtonItem = UIBarButtonItem(title: "today", style: .done, target: self, action: #selector(setToday))
let selectButtonItem = UIBarButtonItem(title: "select", style: .done, target: self, action: #selector(tellCalenderText))
let toolbarItem = [space, flexSpaceItem, todayButtonItem, selectButtonItem]
toolbar.setItems(toolbarItem, animated: true)
}
return toolbar
}
#objc func tellCalenderText(completion: ((_ titleText: String) -> Void)){
//I want to pass text here.
if text != "" {
guard let titleText = text else {return}
completion(titleText)
} else {
return
}
}
ViewController
class Calender1ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
private let selectDate = HourDatePicker()
private var keepDate: [String] = []
#IBOutlet weak var timeTextView: UITextView!
#IBOutlet weak var dateText: HourDatePicker!
#IBOutlet weak var calenderTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.calenderTableView.delegate = self
self.calenderTableView.dataSource = self
selectDate.tellCalenderText {[weak self] (titleText) in
self?.bringDate(title: titleText)
}
}
func bringDate(title: String){
print("title: \(title)")
self.keepDate.append(title)
timeTextView.text.append(contentsOf: "\(title)\n")
}
Thank you.
This is error log.
error log
First, I think you're getting a bit messed up by having:
private let selectDate = HourDatePicker()
and having:
#IBOutlet weak var dateText: HourDatePicker!
and then making use of selectDate inside viewDidLoad()...
Give this a try. I only made a few changes, and tried to include enough comments to make it clear. I think you'll find this a much more straight-forward way of getting your custom HourDatePicker class to pass information back to the view controller:
class HourDatePicker: UITextField {
var datePicker = UIDatePicker()
override init(frame: CGRect) {
super.init(frame: frame)
commominit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commominit()
}
func commominit(){
text = ""
datePicker.datePickerMode = .dateAndTime
datePicker.minuteInterval = 30
datePicker.locale = Locale(identifier: "ja")
datePicker.addTarget(self, action: #selector(setText), for: .valueChanged)
setText()
inputView = datePicker
inputAccessoryView = customPicker()
}
#objc func setToday(){
datePicker.date = Date()
}
#objc func setText(){
let f = DateFormatter()
f.dateStyle = .full
f.timeStyle = .short
f.locale = Locale(identifier: "ja")
textColor = .black
text = "\(f.string(from: datePicker.date))"
}
private func customPicker() -> UIToolbar {
let toolbar = UIToolbar()
toolbar.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: 40)
let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: self, action: nil)
space.width = 100
let flexSpaceItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
let todayButtonItem = UIBarButtonItem(title: "today", style: .done, target: self, action: #selector(setToday))
let selectButtonItem = UIBarButtonItem(title: "select", style: .done, target: self, action: #selector(tellCalenderText))
let toolbarItem = [space, flexSpaceItem, todayButtonItem, selectButtonItem]
toolbar.setItems(toolbarItem, animated: true)
return toolbar
}
// "callback" closure
var tellController: ((String) ->())?
// triggered by "select" bar button tap
#objc func tellCalenderText() -> Void {
// get text from self
guard let t = text else {
return
}
// execute the callback closure
tellController?(t)
}
// #objc func tellCalenderText(completion: ((_ titleText: String) -> Void)){
// //I want to pass text here.
// if text != "" {
// guard let titleText = text else {return}
// completion(titleText)
// } else {
// return
// }
//
// }
}
//ViewController
class Calender1ViewController: UIViewController {
// not needed
//private let selectDate = HourDatePicker()
private var keepDate: [String] = []
// UITextView connected via Storyboard
#IBOutlet weak var timeTextView: UITextView!
// UITextField set to HourDatePicker, connected via Storyboard
#IBOutlet weak var dateText: HourDatePicker!
#IBOutlet weak var calenderTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// set the callback closure for the HourDatePicker
dateText.tellController = { [weak self] (titleText) in
self?.bringDate(title: titleText)
}
// not needed
//selectDate.tellCalenderText {[weak self] (titleText) in
// self?.bringDate(title: titleText)
//}
}
func bringDate(title: String){
print("title: \(title)")
self.keepDate.append(title)
timeTextView.text.append(contentsOf: "\(title)\n")
}
}

Swift - load initial data from mysql into uidatepicker (not from a simple uipiker)

How can I load data into a pickerdate from mysql?
As it is now, I can load the correct data on each text filed. The problem is: the uidatepicker remembers only 1 value and it doesnt load the other one.
In the picture I show that when clicked on Date of Issue text field, it shows the value of Due Date on the pickerView. The correct should be: December 25 2000
Milan helped me on the creation of selecting a date, using the same function ==> link to the question
View Controller
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
//show on text field
dateFormatter.dateFormat = "dd MMM yyyy"
textField.text = dateFormatter.string(from: thePicker.date)
//formated to store on mysql
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, date: String) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
if let fullDate = dateFormatter.date(from: date) {
thePicker.date = fullDate
dateFormatter.dateFormat = "dd MMM yyyy"
let finalDate: String = dateFormatter.string(from: fullDate)
textField.text = finalDate
}
textField.inputView = thePicker
let toolbar = AccessoryToolbar(for: textField)
toolbar.accessoryDelegate = self
}
override func viewDidLoad() {
super.viewDidLoad()
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
//data will be loaded from an API to a server. Hard Coded now just for testing
setUpTextFieldPicker(textField: dateIssueTextField, date:"2000-12-25" )
setUpTextFieldPicker(textField: dueDateTextField, date:"2010-05-03")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
}
}
Helper Class
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)
}
}
small note: I think the data should be read and assigned on viewWillAppear.
You can fix the problem by two ways:
Create two Date objects for each text field, and update new value
for that object when you hit Done button. Update the date picker value based on that date when the text field becomes the first responder.
Update the date picker value when text field becomes the first
responder, you can check this code:
//1. Add UITextFieldDelegate
class InvoiceViewController: UIViewController, AccessoryToolbarDelegate, UITextFieldDelegate {
//......
//2. Set delegate for the textfields
override func viewDidLoad() {
super.viewDidLoad()
dateIssueTextField.delegate = self
dueDateTextField.delegate = self
//......
}
//3. Update the value of thePicker.date
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
if let fullDate = dateFormatter.date(from: textField.text) {
thePicker.date = fullDate
}
return true
}
}

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

Show Present and Upcoming days on picker view

#IBOutlet weak var tvDueDate: UITextField!
#IBOutlet weak var dateText: UITextField!
var datePicker = UIDatePicker()
var dayPicker = UIDatePicker()
let dateFormatter = NSDateFormatter()
let timeFormatter = NSDateFormatter()
var date_time:String!
var timeAs_24Hour:String!
var selected_date:String!
var timeAs_12Hour:String!
override func viewDidLoad() {
super.viewDidLoad()
setupDatePicker()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func setupDatePicker() {
datePicker.datePickerMode = .Time
dayPicker.datePickerMode = .Date
let toolBar = UIToolbar()
toolBar.barStyle = .Default
toolBar.translucent = true
toolBar.tintColor = UIColor.blueColor()
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: #selector(ViewController.doneClick))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: #selector(ViewController.cancelClick))
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.userInteractionEnabled = true
tvDueDate.inputView = datePicker
tvDueDate.inputAccessoryView = toolBar
tvDueDate.tintColor = UIColor.clearColor()
dateText.inputView = dayPicker
dateText.inputAccessoryView = toolBar
dateText.tintColor = UIColor.clearColor()
}
func doneClick() {
dateFormatter.dateFormat = "yyyy-MM-dd"
timeFormatter.dateFormat = "hh:mm a"
dateFormatter.dateStyle = .MediumStyle
let selected_Final_Date = dateFormatter.stringFromDate(dayPicker.date)
let selected_Final_Time = timeFormatter.stringFromDate(datePicker.date)
self.dateText.text = selected_Final_Date.uppercaseString
self.tvDueDate.text = selected_Final_Time.uppercaseString
tvDueDate.resignFirstResponder()
dateText.resignFirstResponder()
}
func cancelClick() {
tvDueDate.resignFirstResponder()
dateText.resignFirstResponder()
}
I'm using Swift, and trying to create 2 picker views on 2 text field clicks. On the first text field, it's opening all days month year, on 2nd it's showing timing. I want to show present day and all upcoming days on 1st text field click, and on the 2nd text field, it should show time between 9 am to 6 pm only with a 30min difference like 9, 9:30, 10:00, 10:30, 11:00, 11:30.
You should use a UIDatePicker (or two, if you're determined to select the date in one field and the time in another)
They are designed for exactly this purpose.
They have settings they let you determine whether the user can pick dates, or dates and times, or just times. They also have settings they let you limit the range of dates or times that the user can pick. The Xcode documentation is a wonderful thing. You should try it.

multiple UIDatePicker one uitextfield

In my ViewController there are several UiTextfield.
I intend to use a single UIDatePicker that is expected to respond accordingly.
my code only responds to event generated by second textfield and not the first one.
I just need to determine which UITextField has generated the event...
import UIKit
class ViewController: UIViewController , UITextFieldDelegate {
var datePicker = UIDatePicker()
#IBOutlet weak var tvDueDate: UITextField!
#IBOutlet weak var tvOtherDate: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//setupDatePicker()
self.tvDueDate.tag = 0
self.tvOtherDate.tag = 1
//setupDatePicker(textField)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldDidEndEditing(textField: UITextField) {
setupDatePicker(textField)
}
func textFieldDidBeginEditing(textField: UITextField) {
setupDatePicker(textField)
}
func setupDatePicker(text: UITextField) {
// Sets up the "button"
//tvDueDate.text = "Pick a due date"
//tvDueDate.textAlignment = .Center
// Removes the indicator of the UITextField
//tvDueDate.tintColor = UIColor.clearColor()
// Specifies intput type
datePicker.datePickerMode = .Date
// Creates the toolbar
let toolBar = UIToolbar()
toolBar.barStyle = .Default
toolBar.translucent = true
toolBar.tintColor = UIColor(red: 92/255, green: 216/255, blue: 255/255, alpha: 1)
toolBar.sizeToFit()
// Adds the buttons
var doneButton = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: "doneClick")
var spaceButton = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
var cancelButton = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: "cancelClick")
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.userInteractionEnabled = true
// Adds the toolbar to the view
if text.tag == 0{
self.tvDueDate.inputView = datePicker
self.tvDueDate.inputAccessoryView = toolBar
}
else
{
self.tvOtherDate.inputView = datePicker
self.tvOtherDate.inputAccessoryView = toolBar
}
}
func doneClick() {
var dateFormatter = NSDateFormatter()
//dateFormatter.dateFormat = "dd-MM-yyyy"
dateFormatter.dateStyle = .ShortStyle
if tvDueDate.isFirstResponder(){
tvDueDate.text = dateFormatter.stringFromDate(datePicker.date)
tvDueDate.resignFirstResponder()
}else{
tvOtherDate.text = dateFormatter.stringFromDate(datePicker.date)
tvOtherDate.resignFirstResponder()
}
}
func cancelClick() {
if tvDueDate.isFirstResponder(){
tvDueDate.resignFirstResponder()
}else{
tvOtherDate.resignFirstResponder()
}
}
}
Give unique tags to your UITextFields and use UITextField delegates.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//setupDatePicker()
self.tvDueDate.tag = 0
self.tvOtherDate.tag = 1
self.tvDueDate.delegate = self
self.tvOtherDate.delegate = self
//setupDatePicker(textField)
}
// UITextField Delegates
func textFieldDidBeginEditing(textField: UITextField) {
println("TextField did begin editing method called")
if textField.tag == 0
..........
if textField.tag == 2
....
}
func textFieldDidEndEditing(textField: UITextField) {
println("TextField did end editing method called")
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
println("TextField should begin editing method called")
return true;
}
You are calling
setupDatePicker()
From viewDidLoad and your code is
if tvDueDate.isFirstResponder(){
tvDueDate.inputView = datePicker
tvDueDate.inputAccessoryView = toolBar
}
else
{
tvOtherDate.inputView = datePicker
tvOtherDate.inputAccessoryView = toolBar
}
adds picker as inputAccessoryView . As at the point of viewDidLoad no text field is FirstResponder that's why only your else part is excited and its only added to tvOtherDate field.
I would recommend to call it from the textfield delegate method (will begin editing or didbegineditting) or call it on tap. And to check from which it is called also pass the textfield or you can use tag.
Adding Delegates and tags to my UiTextField helped me.......
import UIKit
class ViewController: UIViewController , UITextFieldDelegate {
var datePicker = UIDatePicker()
#IBOutlet weak var tvDueDate: UITextField!
#IBOutlet weak var tvOtherDate: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//setupDatePicker()
self.tvDueDate.tag = 0
self.tvOtherDate.tag = 1
//setupDatePicker(textField)
self.tvDueDate.delegate = self
self.tvOtherDate.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldDidEndEditing(textField: UITextField) {
setupDatePicker(textField)
}
func textFieldDidBeginEditing(textField: UITextField) {
setupDatePicker(textField)
}
func setupDatePicker(text: UITextField) {
// Sets up the "button"
//tvDueDate.text = "Pick a due date"
//tvDueDate.textAlignment = .Center
// Removes the indicator of the UITextField
//tvDueDate.tintColor = UIColor.clearColor()
// Specifies intput type
datePicker.datePickerMode = .Date
// Creates the toolbar
let toolBar = UIToolbar()
toolBar.barStyle = .Default
toolBar.translucent = true
toolBar.tintColor = UIColor(red: 92/255, green: 216/255, blue: 255/255, alpha: 1)
toolBar.sizeToFit()
// Adds the buttons
var doneButton = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: "doneClick")
var spaceButton = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
var cancelButton = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: "cancelClick")
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.userInteractionEnabled = true
// Adds the toolbar to the view
if text.tag == 0{
self.tvDueDate.inputView = datePicker
self.tvDueDate.inputAccessoryView = toolBar
}
else
{
self.tvOtherDate.inputView = datePicker
self.tvOtherDate.inputAccessoryView = toolBar
}
}
func doneClick() {
var dateFormatter = NSDateFormatter()
//dateFormatter.dateFormat = "dd-MM-yyyy"
dateFormatter.dateStyle = .ShortStyle
if tvDueDate.isFirstResponder(){
tvDueDate.text = dateFormatter.stringFromDate(datePicker.date)
tvDueDate.resignFirstResponder()
}else{
tvOtherDate.text = dateFormatter.stringFromDate(datePicker.date)
tvOtherDate.resignFirstResponder()
}
}
func cancelClick() {
if tvDueDate.isFirstResponder(){
tvDueDate.resignFirstResponder()
}else{
tvOtherDate.resignFirstResponder()
}
}
}

Resources