Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIDatePicker bug? UIControlEventValueChanged after hitting minimum internal

I've run into a weird effect that sure looks like a bug in iOS7 -- but often in the past, when I have thought I found a bug in Apple's APIs, it has turned out to be my own misunderstanding.

I have a UIDatePicker with datePickerMode = UIDatePickerModeCountDownTimer and minuteInterval = 5. I initialize the duration to 1 hour, and present it to the user, where it appears as a two-column picker with hours and minutes. (So far so good.)

The user is thinking "20 minutes," and so scrolls the Hour column to 0. At this point the picker reads 0 hours and 0 minutes, and iOS7 is not cool with that, so it automatically scrolls the minute wheel to 5. My UIControlEventValueChanged handler gets invoked, and the countDownDuration reads 5 minutes. (Still good.)

Now the user grabs the minute wheel and drags it to 20. AND... my UIControlEventValueChanged handler does not get called. (Bad.)

If I have some other event in the UI check the date picker at this point, I do see the countDownDuration is set to 20. But I had no way of knowing that the user changed it, at the moment it was changed. This is very repeatable: it always happens on the first change AFTER the picker refuses to be set to 0 (advancing itself to 5 minutes).

Note that this is in iOS7; it does not occur in iOS6 (perhaps because the picker there is perfectly content to be set to 0 minutes).

So... am I missing something here? Or is this a genuine bug in iOS7? And in the latter case, does anybody know a work-around better than having some timer periodically check the current interval?

like image 927
Joe Strout Avatar asked Nov 24 '13 22:11

Joe Strout


1 Answers

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

Swift 5:

DispatchQueue.main.async {     self.myDatePicker.countDownDuration = aNewDuration } 
like image 130
Positron Avatar answered Oct 01 '22 08:10

Positron