UIDatePicker bug? UIControlEventValueChanged after hitting minimum internal

♀尐吖头ヾ 提交于 2019-11-28 04:57:58

I can also confirm that the iOS 7.0.3 UIDatePicker has a bug in it when used in UIDatePickerModeCountDownTimer mode. The picker does not fire the target-action associated with the UIControlEventValueChanged event the first time the user changes the value by scrolling the wheels. It works fine for subsequent changes.

Below is an efficient workaround. Simply enclose the code that sets the initial value of the countDownDuration in a dispatch block to the main loop. Your target-action method will fire every time the wheels are rotated to a new value. This approach has almost no overhead and works quite well on an iPhone 4 and iPad 4.

dispatch_async(dispatch_get_main_queue(), ^{
    self.myDatePicker.countDownDuration = (NSTimeInterval) aNewDuration ;
});

I was still hitting this issue in 7.1 but adding the following to the UIControlEventValueChanged handler fixed it for me.

// Value Changed Event is not firing if minimum value hit
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    [self.myDatePicker setCountDownDuration: self.myDatePicker.countDownDuration];
});

If someone still having problems with datepicker... I'm using Swift / iOS 8 / Xcode 6.3

So solve the problem you should no use

picker.countDownDuration = NSTimeInterval

instead, use setDate

picker.setDate(NSDate, animated: true)

it works direct on viewDidLoad(), don't need to use `queues

If someone still having problems with datepicker... I'm using Swift / iOS 8 / Xcode 6.3

To solve the problem you should not use picker.countDownDuration = NSTimeInterval. Use .setDate(NSDate, animated: true).

it works direct on viewDidLoad(), don't need to use queues

The complete snippet:

override func viewDidLoad() {
    super.viewDidLoad()
    picker.setDate(setDateFromSeconds(seconds), animated: true)
}

func setDateFromSeconds(seconds: Double) -> (NSDate) {
    let intSeconds = Int(seconds)
    let minutes = (intSeconds / 60) % 60
    let hours = intSeconds / 3600
    let dateString = NSString(format: "%0.2d:%0.2d", hours, minutes)

    let dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "hh:mm"
    return dateFormatter.dateFromString(dateString as String) as NSDate!
}

For Swift 3:

DispatchQueue.main.async(execute: {
    yourPicker.countDownDuration = TimeInterval() 
})

Since no answer has been accepted yet. The simplest solution that worked for me in swift 3 is to simply do

datePicker.countDownDuration = seconds

in viewDidAppear instead of viewDidLoad

Swift 4

@IBOutlet weak var fromPickerView: UIDatePicker!


@objc func toPickerViewDateChanged() {
        fromPickerView.minimumDate = toPickerView.date
    }
    override func viewDidLoad() {
        super.viewDidLoad()



toPickerView.backgroundColor = UIColor.white
    toPickerView.tintColor = .black
    toPickerView.maximumDate = Date()
    toPickerView.addTarget(self, action: 
    #selector(toPickerViewDateChanged), for: UIControlEvents.valueChanged)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!