Search code examples
iosswiftaddtarget

addTarget not firing any event


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

Solution

  • 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!