2013-11-24 7 views
23

Ho avuto un effetto strano che sembra un bug in iOS7 - ma spesso in passato, quando ho pensato di aver trovato un bug nelle API di Apple, è risultato essere il mio proprio malinteso.Bug UIDatePicker? UIControlEventValueChanged dopo aver toccato il minimo interno

Ho un UIDatePicker con datePickerMode = UIDatePickerModeCountDownTimer e minuteInterval = 5. Inizializzo la durata a 1 ora e la presenta all'utente, dove appare come un selettore a due colonne con ore e minuti. (Fin qui tutto bene.)

L'utente sta pensando "20 minuti" e quindi scorre la colonna Ora a 0. A questo punto il selettore legge 0 ore e 0 minuti e iOS7 non è bello con quello, quindi fa scorrere automaticamente la ruota dei minuti su 5. Viene richiamato il gestore My UIControlEventValueChanged e il countDownDuration legge 5 minuti. (Ancora buono)

Ora l'utente afferra la ruota dei minuti e la trascina a 20. E ... il mio gestore di UIControlEventValueChanged non viene chiamato. (Cattivo)

Se ho qualche altro evento nell'interfaccia utente controllare il selettore di date a questo punto, vedo che countDownDuration è impostato su 20. Ma non avevo modo di sapere che l'utente lo ha cambiato, al momento è stato cambiato. Questo è molto ripetibile: accade sempre al primo cambio DOPO che il picker si rifiuta di essere impostato su 0 (avanzando a se stesso fino a 5 minuti).

Si noti che questo è in iOS7; non si verifica in iOS6 (forse perché il selettore è perfettamente contenuto per essere impostato su 0 minuti).

Quindi ... mi manca qualcosa qui? O si tratta di un vero bug in iOS7? E in quest'ultimo caso, qualcuno conosce meglio il funzionamento di un timer che controlla periodicamente l'intervallo corrente?

+0

Riprodotto. Sembra un insetto per me. – Kevin

risposta

33

Posso anche confermare che l'UIDatePicker di iOS 7.0.3 presenta un bug quando utilizzato in modalità UIDatePickerModeCountDownTimer. Il selettore non attiva l'azione di destinazione associata all'evento UIControlEventValueChanged dello prima dell'ora in cui l'utente modifica il valore scorrendo le ruote. Funziona bene per le modifiche successive.

Di seguito è una soluzione efficiente. È sufficiente racchiudere il codice che imposta il valore iniziale di countDownDuration in un blocco di invio sul loop principale. Il tuo metodo di azione target si attiva ogni volta che le ruote vengono ruotate su un nuovo valore. Questo approccio non ha quasi in testa e funziona abbastanza bene su un iPhone 4 e iPad 4.

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

@Rich Posso ancora riprodurre il problema su iOS SDK 7.1 su un iPhone con iOS 7.1. Che configurazione hai dove è stato risolto questo problema? –

+0

Questo è abbastanza strano! Questo bug esiste ancora su iOS 7.1, ma la correzione in questa risposta ha funzionato per me. Grazie. –

+8

Questo errore esiste ancora su iOS 8;/ – Shial

4

ero ancora colpendo questo problema in 7.1, ma aggiungendo la seguente al gestore UIControlEventValueChanged fisso per 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]; 
}); 
+0

Questo ha funzionato per me con iOS 8, mentre la soluzione di Positron no. – fatuhoku

+0

stesso qui, sembra che il ritardo sia necessario – cdstamper

2

Se qualcuno continua ad avere problemi con datepicker ... sto usando Swift/iOS 8/Xcode 6.3

Quindi risolvere il problema si dovrebbe inutile

picker.countDownDuration = NSTimeInterval 

, invece, utilizzare setDate

picker.setDate(NSDate, animated: true) 

funziona direttamente su viewDidLoad(), non serve usare `queues

1

Se qualcuno ha ancora problemi con datepicker ... Sto usando Swift/iOS 8/Xcode 6.3

Per risolvere il problema non utilizzare picker.countDownDuration = NSTimeInterval. Utilizzare .setDate(NSDate, animated: true).

funziona direttamente sul viewDidLoad(), non hanno bisogno di utilizzare queues

Il frammento completo:

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! 
} 
+0

Grazie per aver incluso il codice swift per la conversione dell'intervallo di tempo. Questo ha funzionato per me. Pazzo che questo problema si verifica ancora in iOS 10. – Mikrasya

1

Per Swift 3:

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

Dal momento che nessuna risposta è stata ancora accettata . La soluzione più semplice che ha lavorato per me in rapida 3 è quello di fare semplicemente

datePicker.countDownDuration = secondi

in viewDidAppear invece di viewDidLoad

0

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) 
Problemi correlati