Swift passing parameter on #selector - ios

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

Related

I want in one textfield it can be show keyboard and datepicker

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

Opening UIDatePicker under UITextView

I am writing an app, where when clicking on a UITexView an UIDatePicker opens. I want the UIDatePicker to pop up underneath the UITextView and not to come up as the keyboard from the bottom.
I am just starting with IOS app development and I hope someone can help me.
datePicker = UIDatePicker
and
inputTextfield = UITextField
myCode:
//Function to create the datepicker
func createDatePicker(){
//create instance of the datepicker
datePicker = UIDatePicker()
//sets format, so only day month and year can be selected
//datePicker?.datePickerMode = .date
datePicker?.backgroundColor = .white
datePicker?.addTarget(self, action: #selector(ViewController.dateChanged(datePicker:)), for: .valueChanged)
//to limit the datepicker, you can not pick a date older than yesterday
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())
datePicker?.minimumDate = yesterday
datePicker?.minuteInterval = 30
let loc = Locale(identifier: "de")
datePicker?.locale = loc
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.viewTapped(gesturRecognizer:)))
view.addGestureRecognizer(tapGesture)
inputTextfield.inputView = datePicker
//create a toolbar
let toolbar = UIToolbar()
toolbar.sizeToFit()
//add done button to the toolbar
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(doneClicked))
toolbar.setItems([doneButton], animated: true)
inputTextfield.inputAccessoryView = toolbar
}
//function to select a date
#objc func dateChanged(datePicker: UIDatePicker){
//selected date by the user
let dateFormate = DateFormatter()
//Jonas das ist vllt für dich relevant, man kann es so verändern wie man will
dateFormate.dateFormat = "MM/dd/yyyy"
inputTextfield.text = dateFormate.string(from: datePicker.date)
}
//function to close the datepicker, when tapping on the inputText again -handler method
#objc func viewTapped(gesturRecognizer: UITapGestureRecognizer){
view.endEditing(true)
}
//function to close the datepicker when clicking on the done button
#objc func doneClicked(){
self.view.endEditing(true)
}
No need to use any third party library. This can be achieved very easily. What I understand is that you want the picker to be displayed below the textfield and not as the input view instead of keyboard. Follow the following code to achieve what you want.
Here, name of my ViewController is TextFieldWithDatePickerVC. Don't get confused with name. With following code you would be able to do this very easily without using any third part library. I am attaching a output video also along with the code.
class TextFieldWithDatePickerVC: UIViewController {
lazy var inputTextfield: UITextField = {
let txtField = UITextField()
txtField.backgroundColor = .white
txtField.borderStyle = .roundedRect
txtField.translatesAutoresizingMaskIntoConstraints = false
txtField.placeholder = "Click me to open date picker"
return txtField
}()
lazy var datePicker: UIDatePicker = {
let picker = UIDatePicker()
picker.backgroundColor = .white
picker.addTarget(self, action: #selector(TextFieldWithDatePickerVC.dateChanged(_:)), for: .valueChanged)
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())
picker.minimumDate = yesterday
picker.minuteInterval = 30
let loc = Locale(identifier: "de")
picker.locale = loc
picker.translatesAutoresizingMaskIntoConstraints = false
return picker
}()
lazy var doneToolBar: UIToolbar = {
let toolbar = UIToolbar()
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(doneClicked))
toolbar.setItems([doneButton], animated: true)
toolbar.translatesAutoresizingMaskIntoConstraints = false
return toolbar
}()
lazy var pickerContainer: UIView = {
let view = UIView()
view.backgroundColor = .white
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
setupAutoLayout()
pickerContainer.isHidden = true
inputTextfield.delegate = self
hideDatePicker()
}
func showDatePickerView() {
DispatchQueue.main.async {
self.pickerContainer.isHidden = false
}
}
func hideDatePicker() {
DispatchQueue.main.async {
self.pickerContainer.isHidden = true
}
}
func setupAutoLayout() {
self.view.addSubview(inputTextfield)
self.view.addSubview(pickerContainer)
self.view.bringSubview(toFront: pickerContainer)
pickerContainer.addSubview(doneToolBar)
pickerContainer.addSubview(datePicker)
NSLayoutConstraint.activate([
inputTextfield.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30),
inputTextfield.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -30),
inputTextfield.topAnchor.constraint(equalTo: view.topAnchor, constant: 60),
pickerContainer.topAnchor.constraint(equalTo: inputTextfield.bottomAnchor, constant: 5),
pickerContainer.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30),
pickerContainer.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -30),
pickerContainer.heightAnchor.constraint(equalToConstant: datePicker.intrinsicContentSize.height + doneToolBar.intrinsicContentSize.height),
doneToolBar.topAnchor.constraint(equalTo: pickerContainer.topAnchor, constant: 0),
doneToolBar.leftAnchor.constraint(equalTo: pickerContainer.leftAnchor, constant: 0),
doneToolBar.rightAnchor.constraint(equalTo: pickerContainer.rightAnchor, constant: 0),
datePicker.bottomAnchor.constraint(equalTo: pickerContainer.bottomAnchor, constant: 0),
datePicker.leftAnchor.constraint(equalTo: pickerContainer.leftAnchor, constant: 0),
datePicker.rightAnchor.constraint(equalTo: pickerContainer.rightAnchor, constant: 0)
])
}
#objc func dateChanged(_ sender: UIDatePicker) {
print(sender.date)
inputTextfield.text = sender.date.description
}
#objc func doneClicked() {
hideDatePicker()
}
}
extension TextFieldWithDatePickerVC: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.resignFirstResponder()
showDatePickerView()
}
}
Here is a third party library which I guess will meet your expectation :
https://github.com/angelopino/APJTextPickerView
This subclasses the UITextField and very useful. Refer the example for more details.
See this: This would be helpfull for you.
https://blog.apoorvmote.com/change-textfield-input-to-datepicker/
let dateFormatter = DateFormatter()
let locale = NSLocale.current
var datePicker : UIDatePicker!
let toolBar = UIToolbar()
func doDatePicker() {
// DatePicker
self.datePicker = UIDatePicker(frame:CGRect(x: 0, y: UIScreen.main.bounds.height - 200.0, width: UIScreen.main.bounds.width, height: 200))
self.datePicker?.backgroundColor = UIColor.white
self.datePicker?.datePickerMode = UIDatePickerMode.dateAndTime
datePicker.center = view.center
view.addSubview(self.datePicker)
// ToolBar
toolBar.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 240.0, width: UIScreen.main.bounds.width, height: 44.0)
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(doneClick))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelClick))
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: true)
self.view.addSubview(toolBar)
self.toolBar.isHidden = false
}
#objc func doneClick() {
let dateFormatter1 = DateFormatter()
dateFormatter1.dateStyle = .medium
dateFormatter1.timeStyle = .none
//self.datePicker.resignFirstResponder()
datePicker.isHidden = true
self.toolBar.isHidden = true
}
#objc func cancelClick() {
datePicker.isHidden = true
self.toolBar.isHidden = true
}

How to create Custom UI Date PickerViews in the same UIView in swift

Im trying to have two different date pickerViews on the same viewController and let them represent different data. I have tried a different ways to do this, but both date picker views showing same Data, but can't put it all together.I'm new to swift programming. Any help would be awesome!
#IBOutlet weak var EventStart: UITextField!
var datepicker = UIDatePicker()
var datepicker2 = UIDatePicker()
#IBOutlet weak var EventEnd: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
createDatePicker()
Event.delegate = self
eventName.delegate = self
// Do any additional setup after loading the view.
}
func createDatePicker(){
datepicker.datePickerMode = .dateAndTime
datepicker2.datePickerMode = .dateAndTime
let toolbar = UIToolbar()
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressed))
toolbar.setItems([doneButton], animated: false)
EventEnd.inputAccessoryView = toolbar
EventEnd.inputView = datepicker2
EventStart.inputAccessoryView = toolbar
EventStart.inputView = datepicker
}
func donePressed(){
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
EventStart.text = dateFormatter.string(from: datepicker.date)
EventEnd.text = dateFormatter.string(from: datepicker2.date)
print(EventStart)
print(EventEnd)
self.view.endEditing(true)
}
#IBOutlet weak var EventStart: UITextField!
var datepicker = UIDatePicker()
var datepicker2 = UIDatePicker()
#IBOutlet weak var EventEnd: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.addDatePicker(datepicker, textfield:EventStart , selector: #selector(ViewController.donePressed))
self.addDatePicker(datepicker2 , textfield:EventEnd ,selector: #selector(ViewController.donePressed2))
// Do any additional setup after loading the view.
}
func addDatePicker(_ datepicker : UIDatePicker, textfield: UITextField, selector: Selector) {
let toolbar = UIToolbar()
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action:selector)
toolbar.setItems([doneButton], animated: false)
textfield.inputAccessoryView = toolbar
textfield.inputView = datepicker
}
func donePressed(){
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
EventStart.text = dateFormatter.string(from: datepicker.date)
print(EventStart)
self.view.endEditing(true)
}
func donePressed2(){
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
EventEnd.text = dateFormatter.string(from: datepicker2.date)
print(EventEnd)
self.view.endEditing(true)
}
The simple thing is to create two separate method for two of em. Also do not initialized them on view load.
This is my code for doing it.
var objDatePickerFrom: UIDatePicker!
var objDatePickerTo: UIDatePicker!
Then on respective button tap, I init them as below (you also do this in textview's delegate method if you do not use buttons.)
#IBAction func btnFromDateTapped(_ sender: UIButton) {
self.initDatePikerFrom(frame: self.view.frame)
}
#IBAction func btnToDateTapped(_ sender: UIButton) {
self.initDatePikerTo(frame: self.view.frame)
}
Below are the methods for init the date pickers.
func initDatePikerFrom(frame: CGRect) {
self.objDatePickerFrom = UIDatePicker()
objDatePickerFrom.backgroundColor = UIColor.white
objDatePickerFrom.datePickerMode = .date
if DeviceType.IS_IPHONE_4_OR_LESS
{
objDatePickerFrom?.frame.size = CGSize(width: frame.size.width, height: 150)
}
self.txtFromDate.inputView = objDatePickerFrom
objDatePickerFrom.maximumDate = Date()
if self.txtFromDate.text! != "" {
objDatePickerFrom.date = CommonFunctions.getDate(date: self.txtFromDate.text!)
}
self.view.bringSubview(toFront: objDatePickerFrom)
let numberToolbar = UIToolbar(frame: CGRect.init(x: 0.0, y: 0.0, width: frame.size.width, height: 40.0))
numberToolbar.barStyle = UIBarStyle.default
numberToolbar.barTintColor = NavigationBGColor
numberToolbar.layer.borderColor = UIColor(red: 79.0/255.0, green: 157.0/255.0, blue: 191.0/255.0, alpha: 1.0).cgColor
numberToolbar.layer.borderWidth = 0.0
let lblSelect = UILabel(frame: CGRect.init(x: 0, y: 0, width: 150, height: 30))
lblSelect.text = "Select Date"
lblSelect.textColor = WhiteFontColor
lblSelect.textAlignment = .center
let btnBarCancel = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(MyAccountViewController.btnCancelFromDateClick(_:)) )
btnBarCancel.tintColor = WhiteFontColor
let btnBarDone = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(MyAccountViewController.btnDoneFromDateClick(_:)) )
btnBarDone.tintColor = WhiteFontColor
numberToolbar.items = [
btnBarCancel,
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil),
UIBarButtonItem.init(customView: lblSelect),
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil),
btnBarDone]
numberToolbar.sizeToFit()
self.txtFromDate.inputAccessoryView = numberToolbar
self.txtFromDate.isUserInteractionEnabled = true
self.txtFromDate.delegate = self
self.txtFromDate.becomeFirstResponder()
}
func initDatePikerTo(frame: CGRect) {
self.objDatePickerTo = UIDatePicker()
self.objDatePickerTo.backgroundColor = UIColor.white
self.objDatePickerTo.datePickerMode = .date
if DeviceType.IS_IPHONE_4_OR_LESS
{
self.objDatePickerTo?.frame.size = CGSize(width: frame.size.width, height: 150)
}
self.txtToDate.inputView = self.objDatePickerTo
self.objDatePickerTo.maximumDate = Date()
if self.txtToDate.text! != "" {
self.objDatePickerTo.date = CommonFunctions.getDate(date: self.txtToDate.text!)
}
self.view.bringSubview(toFront: self.objDatePickerTo)
let numberToolbar = UIToolbar(frame: CGRect.init(x: 0.0, y: 0.0, width: frame.size.width, height: 40.0))
numberToolbar.barStyle = UIBarStyle.default
numberToolbar.barTintColor = NavigationBGColor
numberToolbar.layer.borderColor = UIColor(red: 79.0/255.0, green: 157.0/255.0, blue: 191.0/255.0, alpha: 1.0).cgColor
numberToolbar.layer.borderWidth = 0.0
let lblSelect = UILabel(frame: CGRect.init(x: 0, y: 0, width: 150, height: 30))
lblSelect.text = "Select Date"
lblSelect.textColor = WhiteFontColor
lblSelect.textAlignment = .center
let btnBarCancel = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(MyAccountViewController.btnCancelToDateClick(_:)) )
btnBarCancel.tintColor = WhiteFontColor
let btnBarDone = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(MyAccountViewController.btnDoneToDateClick(_:)) )
btnBarDone.tintColor = WhiteFontColor
numberToolbar.items = [
btnBarCancel,
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil),
UIBarButtonItem.init(customView: lblSelect),
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil),
btnBarDone]
numberToolbar.sizeToFit()
self.txtToDate.inputAccessoryView = numberToolbar
self.txtToDate.isUserInteractionEnabled = true
self.txtToDate.delegate = self
self.txtToDate.becomeFirstResponder()
}
The other related methods similar to your donePressed() are as below.
func btnDoneFromDateClick(_ sendre: AnyObject)
{
let date = CommonFunctions.getStrDate(date: self.objDatePickerFrom.date)
self.txtFromDate.text = "\(date.day) \(date.month) \(date.year)"
self.txtFromDate.resignFirstResponder()
self.txtFromDate.isUserInteractionEnabled = false
}
func btnDoneToDateClick(_ sendre: AnyObject)
{
let date = CommonFunctions.getStrDate(date: self.objDatePickerTo.date)
self.txtToDate.text = "\(date.day) \(date.month) \(date.year)"
self.txtToDate.resignFirstResponder()
self.txtToDate.isUserInteractionEnabled = false
}
May this will help you.
Happy Coding :)

app works on simulator but not on ios device

I have an app (using Swift) that calculates the difference between two dates. It works fine on the Simulator but when I run it on an iOS device, it crashes and gives the following error message:
changing property masksToBounds in transform-only layer, will have no effect
fatal error:
unexpectedly found nil while unwrapping an Optional value
(lldb)
In the Debug Navigator I found the following two error messages:
If anyone can see what I am doing wrong, I would be very grateful. Thanks!
This is the View Controller code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var startDateTextField: UITextField!
#IBOutlet weak var endDateTextField: UITextField!
#IBOutlet weak var resultNumberOfDays: UILabel!
#IBOutlet weak var resultWeeksAndDays: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(red: 232/255, green: 232/255, blue: 232/255, alpha: 1.0)
let toolBar = UIToolbar(frame: CGRectMake(0, self.view.frame.size.height/6, self.view.frame.size.width, 40.0))
toolBar.layer.position = CGPoint(x: self.view.frame.size.width/2, y: self.view.frame.size.height-20.0)
toolBar.barStyle = UIBarStyle.BlackTranslucent
toolBar.tintColor = UIColor.whiteColor()
UIToolbar.appearance().barTintColor = UIColor(red: 179/255, green: 179/255, blue: 179/255, alpha: 1.0)
let todayBtn = UIBarButtonItem(title: "Today", style: UIBarButtonItemStyle.Plain, target: self, action: "tappedToolBarBtn:")
let okBarBtn = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "donePressed:")
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil)
let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width / 3, height: self.view.frame.size.height))
label.font = UIFont(name: "Helvetica Neue", size: 13)
label.backgroundColor = UIColor.clearColor()
label.textColor = UIColor.whiteColor()
label.text = "Select a Start Date"
label.textAlignment = NSTextAlignment.Center
let textBtn = UIBarButtonItem(customView: label)
toolBar.setItems([todayBtn,flexSpace,textBtn,flexSpace,okBarBtn], animated: true)
startDateTextField.inputAccessoryView = toolBar
let toolBar2 = UIToolbar(frame: CGRectMake(0, self.view.frame.size.height/6, self.view.frame.size.width, 40.0))
toolBar2.layer.position = CGPoint(x: self.view.frame.size.width/2, y: self.view.frame.size.height-20.0)
toolBar2.barStyle = UIBarStyle.BlackTranslucent
toolBar2.tintColor = UIColor.whiteColor()
UIToolbar.appearance().barTintColor = UIColor(red: 107/255, green: 107/255, blue: 107/255, alpha: 1.0)
let todayBtn2 = UIBarButtonItem(title: "Today", style: UIBarButtonItemStyle.Plain, target: self, action: "secondTappedToolBarBtn:")
let okBarBtn2 = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "secondDonePressed:")
let flexSpace2 = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil)
let label2 = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width / 3, height: self.view.frame.size.height))
label2.font = UIFont(name: "Helvetica Neue", size: 13)
label2.backgroundColor = UIColor.clearColor()
label2.textColor = UIColor.whiteColor()
label2.text = "Select an End Date"
label2.textAlignment = NSTextAlignment.Center
let textBtn2 = UIBarButtonItem(customView: label2)
toolBar2.setItems([todayBtn2,flexSpace2,textBtn2,flexSpace2,okBarBtn2], animated: true)
endDateTextField.inputAccessoryView = toolBar2
// 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.
}
func donePressed(sender: UIBarButtonItem) {
startDateTextField.resignFirstResponder()
}
func secondDonePressed(sender: UIBarButtonItem) {
endDateTextField.resignFirstResponder()
}
func tappedToolBarBtn(sender: UIBarButtonItem) {
let dateformatter = NSDateFormatter()
dateformatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateformatter.timeStyle = NSDateFormatterStyle.NoStyle
startDateTextField.text = dateformatter.stringFromDate(NSDate())
startDateTextField.resignFirstResponder()
}
func secondTappedToolBarBtn(sender: UIBarButtonItem) {
let dateformatter = NSDateFormatter()
dateformatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateformatter.timeStyle = NSDateFormatterStyle.NoStyle
endDateTextField.text = dateformatter.stringFromDate(NSDate())
endDateTextField.resignFirstResponder()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
#IBAction func textFieldEditing(sender: UITextField) {
let datePickerView: UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.Date
sender.inputView = datePickerView
datePickerView.addTarget(self, action: Selector("datePickerValueChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}
#IBAction func secondTextFieldEditing(sender: UITextField) {
let datePickerView: UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.Date
sender.inputView = datePickerView
datePickerView.addTarget(self, action: Selector("secondDatePickerValueChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}
func datePickerValueChanged(sender: UIDatePicker) {
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateFormatter.timeStyle = NSDateFormatterStyle.NoStyle
startDateTextField.text = dateFormatter.stringFromDate(sender.date)
}
func secondDatePickerValueChanged(sender: UIDatePicker) {
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateFormatter.timeStyle = NSDateFormatterStyle.NoStyle
endDateTextField.text = dateFormatter.stringFromDate(sender.date)
}
#IBAction func calculateDays(sender: UIButton) {
if startDateTextField.text == "" || endDateTextField.text == "" {
let alert2 = UIAlertController(title: "Oops!", message: "Please Select a Start Date" + "\n" + "and an End Date!", preferredStyle: UIAlertControllerStyle.Alert)
alert2.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert2, animated: true, completion: nil)
}
else {
let start = String(startDateTextField.text!)
let end = String(endDateTextField.text!)
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy"
let startDate:NSDate = dateFormatter.dateFromString(start)!
let endDate:NSDate = dateFormatter.dateFromString(end)!
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day], fromDate: startDate, toDate: endDate, options: [])
let secondNewString = "\(components.day) days"
resultNumberOfDays.text = secondNewString
}
}
#IBAction func calculateWeeksAndDays(sender: UIButton) {
if startDateTextField.text == "" || endDateTextField.text == "" {
let alert2 = UIAlertController(title: "Oops!", message: "Please Select a Start Date" + "\n" + "and an End Date!", preferredStyle: UIAlertControllerStyle.Alert)
alert2.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert2, animated: true, completion: nil)
}
else {
let start = String(startDateTextField.text!)
let end = String(endDateTextField.text!)
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy"
let startDate:NSDate = dateFormatter.dateFromString(start)!
let endDate:NSDate = dateFormatter.dateFromString(end)!
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day], fromDate: startDate, toDate: endDate, options: [])
let days = components.day
let weeks = components.day / 7
let weeksanddays = days % 7
let newString = "\(weeks) weeks + \(weeksanddays) days"
resultWeeksAndDays.text = newString
}
}
#IBAction func resetLabels(sender: AnyObject) {
resultNumberOfDays.text = ""
resultWeeksAndDays.text = ""
}
}

app works fine in Simulator (Xcode 7.1.1) but not on iOS device

I have an app that calculates the difference between two dates. It works fine in the Simulator but not on iOS device (iPad using iOS 9).
When I press the 'calculate difference' buttons on the iPad nothing happens. In the Debug Area of Xcode I get the following error message:
2015-11-16 08:33:32.246 Date-to-Date Calculator[369:64113] <CATransformLayer: >0x17eb95e0> - changing property masksToBounds in transform-only layer, will have >no effect
2015-11-16 08:33:32.250
Date-to-Date Calculator[369:64113] <CATransformLayer: 0x17d8ea30> - changing >property masksToBounds in transform-only layer, will have no effect
2015-11-16 08:33:32.251
Date-to-Date Calculator[369:64113] <CATransformLayer: 0x17d95830> - changing >property masksToBounds in transform-only layer, will have no effect
I've searched this on SO and cannot find a solution.
Does anyone have any suggestions?
Thanks!
Please find View Controller code below:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var startDateTextField: UITextField!
#IBOutlet weak var endDateTextField: UITextField!
#IBOutlet weak var resultNumberOfDays: UILabel!
#IBOutlet weak var resultWeeksAndDays: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(red: 210/255, green: 213/255, blue: 220/255, alpha: 1.0)
let toolBar = UIToolbar(frame: CGRectMake(0, self.view.frame.size.height/6, self.view.frame.size.width, 40.0))
toolBar.layer.position = CGPoint(x: self.view.frame.size.width/2, y: self.view.frame.size.height-20.0)
toolBar.barStyle = UIBarStyle.BlackTranslucent
toolBar.tintColor = UIColor.whiteColor()
UIToolbar.appearance().barTintColor = UIColor(red: 0/255, green: 0/255, blue: 205/255, alpha: 1.0)
let todayBtn = UIBarButtonItem(title: "Today", style: UIBarButtonItemStyle.Plain, target: self, action: "tappedToolBarBtn:")
let okBarBtn = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "donePressed:")
// let okBarBtn = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: "donePressed:")
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil)
let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width / 3, height: self.view.frame.size.height))
label.font = UIFont(name: "Helvetica Neue", size: 13)
label.backgroundColor = UIColor.clearColor()
label.textColor = UIColor.whiteColor()
label.text = "Select a Start Date"
label.textAlignment = NSTextAlignment.Center
let textBtn = UIBarButtonItem(customView: label)
toolBar.setItems([todayBtn,flexSpace,textBtn,flexSpace,okBarBtn], animated: true)
startDateTextField.inputAccessoryView = toolBar
let toolBar2 = UIToolbar(frame: CGRectMake(0, self.view.frame.size.height/6, self.view.frame.size.width, 40.0))
toolBar2.layer.position = CGPoint(x: self.view.frame.size.width/2, y: self.view.frame.size.height-20.0)
toolBar2.barStyle = UIBarStyle.BlackTranslucent
toolBar2.tintColor = UIColor.whiteColor()
UIToolbar.appearance().barTintColor = UIColor(red: 0/255, green: 0/255, blue: 205/255, alpha: 1.0)
let todayBtn2 = UIBarButtonItem(title: "Today", style: UIBarButtonItemStyle.Plain, target: self, action: "secondTappedToolBarBtn:")
let okBarBtn2 = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "secondDonePressed:")
// let okBarBtn2 = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: "secondDonePressed:")
let flexSpace2 = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil)
let label2 = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width / 3, height: self.view.frame.size.height))
label2.font = UIFont(name: "Helvetica Neue", size: 13)
label2.backgroundColor = UIColor.clearColor()
label2.textColor = UIColor.whiteColor()
label2.text = "Select an End Date"
label2.textAlignment = NSTextAlignment.Center
let textBtn2 = UIBarButtonItem(customView: label2)
toolBar2.setItems([todayBtn2,flexSpace2,textBtn2,flexSpace2,okBarBtn2], animated: true)
endDateTextField.inputAccessoryView = toolBar2
// 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.
}
func donePressed(sender: UIBarButtonItem) {
startDateTextField.resignFirstResponder()
}
func secondDonePressed(sender: UIBarButtonItem) {
endDateTextField.resignFirstResponder()
}
func tappedToolBarBtn(sender: UIBarButtonItem) {
let dateformatter = NSDateFormatter()
dateformatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateformatter.timeStyle = NSDateFormatterStyle.NoStyle
startDateTextField.text = dateformatter.stringFromDate(NSDate())
startDateTextField.resignFirstResponder()
}
func secondTappedToolBarBtn(sender: UIBarButtonItem) {
let dateformatter = NSDateFormatter()
dateformatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateformatter.timeStyle = NSDateFormatterStyle.NoStyle
endDateTextField.text = dateformatter.stringFromDate(NSDate())
endDateTextField.resignFirstResponder()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
#IBAction func textFieldEditing(sender: UITextField) {
let datePickerView: UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.Date
sender.inputView = datePickerView
datePickerView.addTarget(self, action: Selector("datePickerValueChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}
#IBAction func secondTextFieldEditing(sender: UITextField) {
let datePickerView: UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.Date
sender.inputView = datePickerView
datePickerView.addTarget(self, action: Selector("secondDatePickerValueChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}
func datePickerValueChanged(sender: UIDatePicker) {
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateFormatter.timeStyle = NSDateFormatterStyle.NoStyle
startDateTextField.text = dateFormatter.stringFromDate(sender.date)
}
func secondDatePickerValueChanged(sender: UIDatePicker) {
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle
dateFormatter.timeStyle = NSDateFormatterStyle.NoStyle
endDateTextField.text = dateFormatter.stringFromDate(sender.date)
}
#IBAction func calculateDays(sender: UIButton) {
if startDateTextField.text! == "" || endDateTextField! == "" {
let alert2 = UIAlertController(title: "Oops!", message: "Please Select a Start Date!", preferredStyle: UIAlertControllerStyle.Alert)
alert2.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert2, animated: true, completion: nil)
}
else {
let start = String(startDateTextField.text!)
let end = String(endDateTextField.text!)
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy"
guard let startDate = dateFormatter.dateFromString(start), endDate = dateFormatter.dateFromString(end) else {
// You don't have dates, show error(print("error"), do no nothing - your choice.
return
}
// let startDate:NSDate = dateFormatter.dateFromString(start)!
// let endDate:NSDate = dateFormatter.dateFromString(end)!
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day], fromDate: startDate, toDate: endDate, options: [])
let secondNewString = "\(components.day) days"
resultNumberOfDays.text = secondNewString
}
}
#IBAction func calculateWeeksAndDays(sender: UIButton) {
if startDateTextField.text! == "" || endDateTextField! == "" {
let alert2 = UIAlertController(title: "Oops!", message: "Please Select an End Date!", preferredStyle: UIAlertControllerStyle.Alert)
alert2.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert2, animated: true, completion: nil)
}
else {
let start = String(startDateTextField.text!)
let end = String(endDateTextField.text!)
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy"
guard let startDate = dateFormatter.dateFromString(start), endDate = dateFormatter.dateFromString(end) else {
// You don't have dates, show error(print("error"), do no nothing - your choice.
return
}
// let startDate:NSDate = dateFormatter.dateFromString(start)!
// let endDate:NSDate = dateFormatter.dateFromString(end)!
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day], fromDate: startDate, toDate: endDate, options: [])
let days = components.day
let weeks = components.day / 7
let weeksanddays = days % 7
let newString = "\(weeks) weeks + \(weeksanddays) days"
resultWeeksAndDays.text = newString
}
}
#IBAction func resetLabels(sender: AnyObject) {
resultNumberOfDays.text = ""
resultWeeksAndDays.text = ""
}
}
I'm willing to bet that your code, as it stands, doesn't "work fine" even in the simulator. For example when I tap on a text field the first time, the date picker doesn't show. I have to tap on the background screen to resignFirstResponder and then tap on the text field again to get the date picker to show.
The problem there is that you aren't instantiating the date picker and connecting it to the text field until after the text field has become the first responder, you need to do that before it becomes first responder. (For example in the viewDidLoad method.)

Resources