带有 UIControlEvents.valueChanged 的日期选择器不适用于第一个值更改事件
Posted
技术标签:
【中文标题】带有 UIControlEvents.valueChanged 的日期选择器不适用于第一个值更改事件【英文标题】:Date Picker with UIControlEvents.valueChanged doesn't work on the first value change event 【发布时间】:2017-04-17 12:15:22 【问题描述】:我正在使用下面的代码来了解日期选择器。它有效,但奇怪的是,当我第一次滚动日期选择器时,预期的变化不会发生。之后它将正常工作。想知道发生了什么。
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)
【问题讨论】:
您是否尝试在 onDatePickerValueChanged 函数中设置断点以查看它是否被调用? 我做了,不是,第一次改变。 这仍然是 ios 10 中的一个错误。参考此内容可能会对您有所帮助 ***.com/questions/20181980/… 【参考方案1】:奇怪。这似乎是设置为 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 错误报告者提交错误报告。根据@Santosh 链接的线程,这个bug 似乎自iOS 7 以来一直存在于UIDatePicker
,这很糟糕。
我看不到解决方法的一个错误是,如果您尝试选择 0 小时 0 分钟的时间间隔,它会切换到 1 分钟,然后,您选择的下一个时间间隔会不触发值改变方法。
间隔日期选择器有很多奇怪的地方,比如你不能指定它来选择秒。如果它足够重要,您可能希望基于通用UIPickerView
创建自己的时间间隔选择器。它不应该那么难。 (特别是如果您不需要担心使用不同时间格式的多个语言环境的本地化。)您只需创建一个带有小时、分钟和(可选)秒的微调器的选择器视图,用您的合法值填充它,你就走了。您可以将其设置为具有可选的最小和最大间隔值。
【讨论】:
谢谢,我一会儿试试。但是现在我有一个新问题,我希望我的文本字段只能通过日期选择器的值更改而不是直接键入键盘来编辑,请问我该如何实现? @CarolHan,请参阅上面对我的代码的编辑。添加一个textField(_:,shouldChangeCharactersInRange:,replacementString:)
函数,该函数返回 false 到您的 UITextFieldDelegate
扩展以上是关于带有 UIControlEvents.valueChanged 的日期选择器不适用于第一个值更改事件的主要内容,如果未能解决你的问题,请参考以下文章
如何翻转正面带有标签而背面带有另一个标签的视图 - 参见图片
CakePHP 如何处理带有/不带有 'id' 字段的 HABTM 表?
带有 RecyclerView 的 DialogFragment 比带有 Recyclerview 的 Fragment 慢