I have the following code and the doneButton
handler is never invoked. Any idea what might be going wrong?
I have tried many different formats for the selector, also with and without parameters. I also made sure that the UIView
received touch events by manually setting userInteractionEnabled = true
. Thanks for any help in advance!
*** UPDATE: I have refactored the code completely, but same behaviour:
My Protocol:
import Foundation
protocol CustomDatePickerDelegate {
func dataPickerDone(date: NSDate)
func dataPickerChanged(date: NSDate)
}
my class:
import Foundation
import UIKit
class CustomDatePicker{
var delegate: CustomDatePickerDelegate?
var datePicker : UIDatePicker = UIDatePicker()
func CreateDatePicker(sender: UITextField) {
if (delegate is UIViewController)
{
let _self = delegate as! UIViewController
let _view = UIView(frame: CGRectMake(0, 0, _self.view.frame.width, 220))
let datePickerView : UIDatePicker = UIDatePicker(frame: CGRectMake(0, 40, 0, 0))
datePickerView.datePickerMode = UIDatePickerMode.Date
let _toolbar = UIToolbar()
let _doneButton = UIBarButtonItem(title: "DONE", style: UIBarButtonItemStyle.Done, target: self, action: #selector(CustomDatePicker.doneButton))
_toolbar.translucent = false
_toolbar.sizeToFit()
_doneButton.accessibilityLabel = "DoneToolbar"
let _spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
_toolbar.setItems([_spaceButton, _doneButton], animated: false)
_toolbar.userInteractionEnabled = true
datePickerView.addTarget(self, action: #selector(CustomDatePicker.handleDatePicker), forControlEvents: UIControlEvents.ValueChanged)
_view.addSubview(datePickerView)
_view.addSubview(_toolbar)
sender.inputView = _view
}
}
@objc func handleDatePicker(sender:UIDatePicker) {
delegate?.dataPickerChanged(datePicker.date)
}
@objc func doneButton(){
delegate?.dataPickerDone(datePicker.date)
}
}
How I use it from the ViewController:
let _dataPicker : CustomDatePicker = CustomDatePicker()
_dataPicker.delegate = self
_dataPicker.CreateDatePicker(dataUI)
func dataPickerDone(date: NSDate) {
dataUI.text = DataFormatejada(date)
dataUI.resignFirstResponder()
}
func dataPickerChanged(date: NSDate) {
dataUI.text = DataFormatejada(date)
}
I found a way to resolve the problem after many hours of try-error. The problem is with the target:self reference in the lines:
let _doneButton = UIBarButtonItem(title: "DONE", style: UIBarButtonItemStyle.Done, target: self, action: #selector(CustomDatePicker.doneButton))
and
_toolbar.userInteractionEnabled = true
datePickerView.addTarget(self, action: #selector(CustomDatePicker.handleDatePicker), forControlEvents: UIControlEvents.ValueChanged)
so what I have done is to create a new property in MyDatePicker class:
var instance : CustomDatePicker?
change those addTarget methods as:
let _doneButton = UIBarButtonItem(title: "DONE", style: UIBarButtonItemStyle.Done, target: instance, action: #selector(CustomDatePicker.doneButton))
_toolbar.userInteractionEnabled = true
datePickerView.addTarget(instance, action: #selector(CustomDatePicker.handleDatePicker), forControlEvents: UIControlEvents.ValueChanged)
and I use it from the ViewController as:
let _dataPicker : CustomDatePicker = CustomDatePicker()
_dataPicker.delegate = self <---- **this made the trick**
_dataPicker.instance = _dataPicker
_dataPicker.CreateDatePicker(dataUI)
but this is not elegant and it is a patch for a more fundamental issue. Why self is not providing the instance of the object and I have to manually pass it back when I create the object?
thanks!