I have making and order app I have take an outlet named: selectedDate and I want to retrieve the selected date to a variable. What should I place in View did load.
#IBOutlet weak var selectedDate: UIDatePicker!
func datePickerChanged(selectedDate:UIDatePicker) {
var dateFormatter = DateFormatter()
dateFormatter.dateStyle = DateFormatter.Style.FullStyle
dateFormatter.timeStyle = DateFormatter.Style.FulltStyle
var strDate = dateFormatter.string(from: selectedDate.date)
}
class ViewController: UIViewController {
#IBOutlet weak var datePicker: UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func datePickerChanged(sender: UIDatePicker) {
print("print \(sender.date)")
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MMM dd, YYYY"
let somedateString = dateFormatter.stringFromDate(sender.date)
print(somedateString) // "somedateString" is your string date
}
}
You have to create a IBAction for datePicker and name it as “datePickerChanged” , just like you create outlet of object. Choose connection type "Action" when you are dragging object to Viewcontroller.
func datePickerChanged(_:UIDatePicker) is a target function.
Did you set the target correctly ?
// Precise that our controller implement the delegate
class MyViewController: UIViewController {
...
#IBOutlet weak var selectedDate: UIDatePicker!
...
override func viewDidLoad() {
super.viewDidLoad()
...
selectedDate.addTarget(self, action: #selector(datePickerChanged(_:)), forControlEvents: .valueChanged) // We register the target function
}
...
// We implement that function
func datePickerChanged(sender:UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .full
dateFormatter.timeStyle = .full
let strDate = dateFormatter.string(from: sender.date)
print(strDate)
}
}
Related
First let me state all the other code you see works as desired except for the UIDatePicker. Right now when I click on the dateTextField the UIDatePicker shows up and I can select a date but when I click the Done button the Date selected is not in the UITextField assigned to it.
One area that may be a place to focus is the doneClicked function. When I initially created it I did not have the (#objc) in front of it and it gave me an error.
/Argument of '#selector' refers to instance method doneClicked() that is not exposed to Objective-C/
So I added (#objc) and the error went away but as stated above the date selected from the UIDatePicker is not being saved in the UITextField.
If you would please explain and show where my code is wrong and how to fix it.
Any help is greatly appreciated in this matter thank you very much.
import Foundation
import UIKit
import Firebase
import FirebaseUI
class TrainViewController: UIViewController{
#IBOutlet weak var trainField: UITextField!
#IBOutlet weak var locationField: UITextField!
#IBOutlet weak var engineField: UITextField!
#IBOutlet weak var dateTextField: UITextField!
let datePicker = UIDatePicker()
#IBAction func saveButton(_ sender: UIButton) {
self.saveText()
trainField.text?.removeAll()
locationField.text?.removeAll()
engineField.text?.removeAll()
dateTextField.text?.removeAll()
self.view.endEditing(true)
}
override func viewDidLoad() {
super.viewDidLoad()
createDatePicker()
}
func saveText() {
let trainText = self.trainField.text!
let locationText = self.locationField.text!
let engineText = self.engineField.text!
let dateStart = self.dateTextField.text!
let db = Firestore.firestore()
let dict = ["train_text": trainText,
"location_text": locationText,
"engine_text": engineText,
"dateStart_text": dateStart]
db.collection("users").addDocument(data: dict)
}
func createDatePicker(){
//format the display of our datepicker
datePicker.datePickerMode = .date
//assign date picker to our textfield
dateTextField.inputView = datePicker
//create a toolbar
let toolbar = UIToolbar()
toolbar.sizeToFit()
//add a done button on this toolbar
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(doneClicked))
toolbar.setItems([doneButton], animated: true)
dateTextField.inputAccessoryView = toolbar
}
#objc func doneClicked(){
//format the date display in textfield
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
}
}
extension TrainViewController : UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
you are not assigning the date in textFiled.
Like : dateTextField.text = dateString
in doneClicked click, get the date form datePicker and assign to dateTextField.
Code:
#objc func doneClicked(){
//format the date display in textfield
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
let dateString = dateFormatter.stringFromDate(datePicker.date)
print(dateString)
dateTextField.text = dateString
}
I have two date pickers. In first I'm selecting a date, and I want second date picker to show the dates after that selected first picker date. Previous dates should be disabled.
else if textFieldType == .RequestFromDate
{
addToolBar()
requestFromdatePicker.datePickerMode = .date
textField.inputView = requestFromdatePicker
requestFromdatePicker.minimumDate = Date()
requestFromdatePicker.addTarget(self, action: #selector(datePickerRequestFromDateClicked(sender:)), for: .valueChanged)
}
else if textFieldType == .RequestToDate
{
addToolBar()
requestTodatePicker.datePickerMode = .date
textField.inputView = requestTodatePicker
requestTodatePicker.minimumDate = requestFromdatePicker.date
requestTodatePicker.date = requestFromdatePicker.date
requestTodatePicker.addTarget(self, action: #selector(datePickerRequestToDateClicked(sender:)), for: .valueChanged)
}
here you can do it like this
import UIKit
class ViewController: UIViewController {
//label for first date picker result
#IBOutlet weak var dateLabel: UILabel!
//first date picker
#IBOutlet weak var datePicker: UIDatePicker!
//secomnd date picker
#IBOutlet weak var secondDatePicker: UIDatePicker!
//Action - Value changed for first date picker
#IBAction func datePickerChanged(_ sender: Any) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = DateFormatter.Style.short
dateFormatter.timeStyle = DateFormatter.Style.short
//here you are getting date as its action for value changed
let strDate = dateFormatter.string(from: datePicker.date)
dateLabel.text = strDate
//here you can just update second date picker date when value of first date picker is changed
secondDatePicker.date = datePicker.date
//set the minimum date so past dates dont be selected
//even if user scroll to past dates they wont be selected
//picker wil automatically come to minimum date
secondDatePicker.minimumDate = datePicker.date
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Link for Video - https://drive.google.com/open?id=1O3avb_n-CPF_7aLat9oX-nzV7k5KklFe
I just begin to learn iOS dev, here I want to show a datePicker and get date from the user, but I don't know how to show a DataPicker from the bottom of screen. After searching, I found that: dataPicker can be activated by a textField simply by "myTextField.inputView = myDatepicker". I did that, but I faced questions:
After activating the datePicker, the user is able to cut, paste the date shown in the textField. Is there some way to disable the selection of the content in the textField and also the editing menu?
Instead of using a textField, if I want to use a UIButton/UILabel/cell to activate the dataPicker, How can I do that?(I mean how to show the DatePicker from the bottom. I found UIButton/UILabel/cell have no method .inputView like textField does)
It may simple, but really confused me, this is the first app I am trying to do. Any help is very much appreciated, especially in detail, in Swift. Thank you very much.
Way 1
Use a button to show the date and a button to show/ hide the datepicker embedded in a view.
class ViewController: UIViewController {
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var datePicker: UIDatePicker!
#IBOutlet weak var chooseDate: UIButton!
#IBAction func toggleDatePicker(_ sender: Any) {
datePicker.isHidden = !datePicker.isHidden
}
override func viewDidLoad() {
dateLabel.text = stringFrom(date: Date())
datePicker.isHidden = true
}
}
extension ViewController: UIPickerViewDelegate {
#IBAction func valueChanged() {
dateLabel.text = stringFrom(date: datePicker.date)
}
private func stringFrom(date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
return dateFormatter.string(from: datePicker.date)
}
}
Way 2
Use a button to show the date and a button to show/ hide the datepicker from the bottom.
Just use the following protocol that I wrote:
protocol DatePickable: class {
var textField: UITextField { get }
var datePicker: UIDatePicker { get }
var isDatePickerVisible: Bool { get set }
}
extension DatePickable {
func prepareDatePickerFor(view: UIView, onChangeAction: Selector) {
datePicker.datePickerMode = UIDatePickerMode.date
datePicker.addTarget(self, action: onChangeAction, for: .valueChanged)
textField.inputView = datePicker
view.addSubview(textField)
}
func toggleDatePicker() {
isDatePickerVisible ? hideDatePicker() : showDatePicker()
isDatePickerVisible = !isDatePickerVisible
}
private func showDatePicker() {
textField.becomeFirstResponder()
}
private func hideDatePicker() {
textField.resignFirstResponder()
}
}
How to use the protocol in you class:
class ViewController: UIViewController, DatePickable {
// Required by Datepickable
var isDatePickerVisible = false
var textField: UITextField = UITextField()
var datePicker: UIDatePicker = UIDatePicker()
// IBOutlets
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var chooseDate: UIButton!
override func viewDidLoad() {
prepareDatePickerFor(view: view,
onChangeAction: #selector(ViewController.onDidChangeDate(_:)))
dateLabel.text = stringFrom(date: Date())
}
#IBAction func toggleDatePickerVisibility(_ sender: Any) {
toggleDatePicker()
}
#IBAction func onDidChangeDate(_ sender: Any) {
dateLabel.text = stringFrom(date: datePicker.date)
}
private func stringFrom(date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
return dateFormatter.string(from: datePicker.date)
}
}
So you have to add textfield delegate and then recognise the right textfield:
let datePicker = UIDatePicker()
func viewDidLoad() {
super.viewDidLoad()
txtDatePicker.delegate = self
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
if textField == txtDatePicker {
showDatePicker()
}
return true
}
Then inside showDatePicker you will tell your picker what mode should it be as follows:
func showDatePicker() {
//Formate Date
datePicker.datePickerMode = .date
// if you need a toolbar, here is a good place to define it
// add datepicker to textField
txtDatePicker.inputView = datePicker
}
Then in delegate function or toolbar selection you do as follows:
func donedatePicker() {
//For date formate
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
txtDatePicker.text = formatter.string(from: datePicker.date)
self.view.endEditing(true)
}
I'm trying to update two buttons with datepicker. Button startDate et endDate. I don't how can I update these butttons with differents datepicker.
Maybe with handler ?
user story : the user click on startDat datepicker is displaying, user choose any date or time, then click on endDate and same action.
EDIT:
class ViewController: UIViewController {
#IBOutlet weak var dateTextField: UITextField!
#IBOutlet weak var dateTextLabel: UILabel!
var whoTriggeredPickerView: UIButton?
#IBOutlet weak var startDateTextButton : UIButton!
#IBOutlet weak var endDateTextButton : UIButton!
#IBOutlet weak var datePick : UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func donePressed(_ sender: UIBarButtonItem) {
dateTextField.resignFirstResponder()
dateTextLabel.resignFirstResponder()
startDateTextButton.resignFirstResponder()
endDateTextButton.resignFirstResponder()
}
func donePressedButton(_ sender :UIButton){
startDateTextButton.resignFirstResponder()
endDateTextButton.resignFirstResponder()
}
func tappedToolBarBtn(_ sender: UIBarButtonItem) {
let dateformatter = DateFormatter()
startDateTextButton.setTitle(dateformatter.string(from: Date()), for: .normal)
endDateTextButton.setTitle(dateformatter.string(from: Date()), for: .normal)
startDateTextButton.resignFirstResponder()
endDateTextButton.resignFirstResponder()
}
func closeDatePicker(){
self.view.endEditing(true)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
closeDatePicker()
}
#IBAction func BtnClicked(sender: UIButton) {
let datePickerView: UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.date
//sender.inputView = datePickerView
self.view.addSubview(datePickerView)
datePickerView.addTarget(self, action: #selector(ViewController.datePickerValueChanged), for: UIControlEvents.valueChanged)
self.whoTriggeredPickerView = sender
}
func datePickerValueChanged(_ sender: UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = DateFormatter.Style.medium
dateFormatter.timeStyle = DateFormatter.Style.none
//dateTextField.text = dateFormatter.string(from: sender.date)
if self.whoTriggeredPickerView == startDateTextButton {
// set startDateBtn title
startDateTextButton.setTitle(dateFormatter.string(from: Date()), for: .normal)
}else if self.whoTriggeredPickerView == endDateTextButton {
// set endDateBtn title
endDateTextButton.setTitle(dateFormatter.string(from: Date()), for: .normal)
}
}
}
For your question:
You can create a tmp variable to record picker is triggered by which button. Then you can decide which button's title you want to set.
//In your view controller:
var whoTriggeredPickerView: UIButton?
//In your BtnClicked function:
self.whoTriggeredPickerView = sender
//Then in datePickerValueChanged function:
if self.whoTriggeredPickerView == StartDateButton {
// set startDateBtn title
}else if self.whoTriggerPickerView == endDateButton {
// set endDateBtn title
}
Some suggestions:
always lowercase the instance name, you are using DatePick as the instance name of UIDatePicker, instead, you should name it as datePicker; for function names as well.
for your case you can use two textfields instead of buttons.
let datePicker = UIDatePicker()
datePicker.addTarget(self, action: #selector(dateChanged), for: .valueChanged)
startDateTextField.inputView = datePicler
endDateTextField.inputView = datePicker
I'm making a To-Do app and I want the value of the date picker as saved by the user into a variable so that I can print that variable in a tableView.
This is my datePicker code:
#IBOutlet weak var datePicker: UIDatePicker!
override func viewDidLoad() {
super.viewDidLoad()
datePicker.minimumDate = Date()
datePicker.locale = Locale.current
datePicker.setValue(UIColor.gray, forKeyPath: "textColor")
}
You can add a specific target to you Picker in order to get a new value.
For example :
#IBOutlet weak var datePicker: UIDatePicker!
var selectedDate : Date?
override func viewDidLoad() {
super.viewDidLoad()
self.datePicker.addTarget(self, action: #selector(self.storeSelectedRow), for: UIControlEvents.valueChanged)
}
func storeSelectedRow(){
self.selectedDate = self.datePicker.date
}
OR
With the storyboard:
As you add you pickerView as a #IBOutlet you can add a #IBAction to your view controller and then get the date of your picker and store it to a variable.
Please see this example that pass the Picker Value to another ViewController
https://drive.google.com/file/d/0B2RAeG6eqtvCbWp1VE5IZ0E2Vkk/view?usp=sharing
Add follow code in viewDidLoad.
datePicker.addTarget(self, action: "dateChanged:",
forControlEvents: UIControlEvents.ValueChanged)
Then get value in func dateChanged.
func dateChanged(datePicker : UIDatePicker){
let formatter = NSDateFormatter()
//formatter
formatter.dateFormat = "yyyy年MM月dd日 HH:mm:ss"
print(formatter.stringFromDate(datePicker.date))
//there you get your label first
//let label = ...
label.text = formatter.stringFromDate(datePicker.date)
}