UIControlEvents.valueChanged 的日期选择器不适用于第一个值更改事件
Date Picker with UIControlEvents.valueChanged doesn't work on the first value change event
我正在使用下面的代码来了解日期选择器。它有效,但奇怪的是,当我第一次滚动日期选择器时,预期的变化不会发生。之后它将正常工作。想知道发生了什么。
import UIKit
import Foundation
class ViewController: UIViewController {
// Place this code inside your ViewController or where you want ;)
var txtField: UITextField = UITextField(frame: CGRect(x: 100, y: 0, width: 300, height: 50))
override func viewDidLoad() {
super.viewDidLoad()
// date picker setup
let datePickerView:UIDatePicker = UIDatePicker()
// choose the mode you want
// other options are: DateAndTime, Time, CountDownTimer
datePickerView.datePickerMode = UIDatePickerMode.countDownTimer
// choose your locale or leave the default (system)
//datePickerView.locale = NSLocale.init(localeIdentifier: "it_IT")
datePickerView.addTarget(self, action: #selector(onDatePickerValueChanged(_:)), for: UIControlEvents.valueChanged)
txtField.inputView = datePickerView
// datepicker toolbar setup
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(ViewController.doneDatePickerPressed))
// if you remove the space element, the "done" button will be left aligned
// you can add more items if you want
toolBar.setItems([space, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
toolBar.sizeToFit()
txtField.inputAccessoryView = toolBar
self.view.addSubview(txtField)
}
func doneDatePickerPressed(){
self.view.endEditing(true)
}
func onDatePickerValueChanged(_ sender: UIDatePicker) {
let (h, m, _) = secondsToHoursMinutesSeconds (duration: sender.countDownDuration)
self.txtField.text = String("\(h) Hours \(m) Minutes")
}
func secondsToHoursMinutesSeconds (duration : Double) -> (Int, Int, Int) {
let seconds:Int = Int(duration)
return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
}
}
奇怪。这似乎是设置为 UIDatePickerMode.countDownTimer
模式的日期选择器中的错误。
您可以通过实施 UITextFieldDelegate
方法 textFieldShouldBeginEditing(_:)
并在短暂的延迟后设置选择器的值来解决 大多数 的失败案例。这是我的测试项目的代码。 (在我的项目中,时间间隔字段称为 optionalTimeField
,时间间隔值是可选的,称为 optionalTime
。您需要更改它以适合您的代码:
编辑:
查看下面的新函数 textField(_:,shouldChangeCharactersInRange:,replacementString:)
extension ViewController: UITextFieldDelegate {
//Add this function to prevent keyboard editing
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
return false
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
if textField === optionalTimeField {
//Set the time interval of the date picker after a short delay
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.datePickerView.countDownDuration = self.optionalTime ?? 60
}
}
return true
}
}
我建议向 Apple bug reporter 提交错误报告。根据链接的@Santosh 线程,看起来这个错误自 iOS 7 以来一直在 UIDatePicker
中,这很糟糕。
我没有看到解决方法的一个错误是,如果您尝试 select 0 小时 0 分钟的时间间隔,它会切换到 1 分钟,然后,下一个时间间隔你 select 不会触发值更改方法。
间隔日期选择器有很多奇怪的地方,比如你不能指定它来选择秒。如果它足够重要,您可能希望基于通用 UIPickerView
创建自己的时间间隔选择器。它不应该那么难。 (特别是如果您不需要担心本地化到使用不同时间格式的多个区域设置。)您只需创建一个带有小时、分钟和(可选)秒微调器的选择器视图,用您的合法值填充它,然后你就走了。您可以将其设置为具有可选的最小和最大间隔值。
我正在使用下面的代码来了解日期选择器。它有效,但奇怪的是,当我第一次滚动日期选择器时,预期的变化不会发生。之后它将正常工作。想知道发生了什么。
import UIKit
import Foundation
class ViewController: UIViewController {
// Place this code inside your ViewController or where you want ;)
var txtField: UITextField = UITextField(frame: CGRect(x: 100, y: 0, width: 300, height: 50))
override func viewDidLoad() {
super.viewDidLoad()
// date picker setup
let datePickerView:UIDatePicker = UIDatePicker()
// choose the mode you want
// other options are: DateAndTime, Time, CountDownTimer
datePickerView.datePickerMode = UIDatePickerMode.countDownTimer
// choose your locale or leave the default (system)
//datePickerView.locale = NSLocale.init(localeIdentifier: "it_IT")
datePickerView.addTarget(self, action: #selector(onDatePickerValueChanged(_:)), for: UIControlEvents.valueChanged)
txtField.inputView = datePickerView
// datepicker toolbar setup
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(ViewController.doneDatePickerPressed))
// if you remove the space element, the "done" button will be left aligned
// you can add more items if you want
toolBar.setItems([space, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
toolBar.sizeToFit()
txtField.inputAccessoryView = toolBar
self.view.addSubview(txtField)
}
func doneDatePickerPressed(){
self.view.endEditing(true)
}
func onDatePickerValueChanged(_ sender: UIDatePicker) {
let (h, m, _) = secondsToHoursMinutesSeconds (duration: sender.countDownDuration)
self.txtField.text = String("\(h) Hours \(m) Minutes")
}
func secondsToHoursMinutesSeconds (duration : Double) -> (Int, Int, Int) {
let seconds:Int = Int(duration)
return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
}
}
奇怪。这似乎是设置为 UIDatePickerMode.countDownTimer
模式的日期选择器中的错误。
您可以通过实施 UITextFieldDelegate
方法 textFieldShouldBeginEditing(_:)
并在短暂的延迟后设置选择器的值来解决 大多数 的失败案例。这是我的测试项目的代码。 (在我的项目中,时间间隔字段称为 optionalTimeField
,时间间隔值是可选的,称为 optionalTime
。您需要更改它以适合您的代码:
编辑:
查看下面的新函数 textField(_:,shouldChangeCharactersInRange:,replacementString:)
extension ViewController: UITextFieldDelegate {
//Add this function to prevent keyboard editing
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
return false
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
if textField === optionalTimeField {
//Set the time interval of the date picker after a short delay
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.datePickerView.countDownDuration = self.optionalTime ?? 60
}
}
return true
}
}
我建议向 Apple bug reporter 提交错误报告。根据链接的@Santosh 线程,看起来这个错误自 iOS 7 以来一直在 UIDatePicker
中,这很糟糕。
我没有看到解决方法的一个错误是,如果您尝试 select 0 小时 0 分钟的时间间隔,它会切换到 1 分钟,然后,下一个时间间隔你 select 不会触发值更改方法。
间隔日期选择器有很多奇怪的地方,比如你不能指定它来选择秒。如果它足够重要,您可能希望基于通用 UIPickerView
创建自己的时间间隔选择器。它不应该那么难。 (特别是如果您不需要担心本地化到使用不同时间格式的多个区域设置。)您只需创建一个带有小时、分钟和(可选)秒微调器的选择器视图,用您的合法值填充它,然后你就走了。您可以将其设置为具有可选的最小和最大间隔值。