【发布时间】:2019-06-13 03:44:21
【问题描述】:
我有一个ViewController 和两个UITextFields,它们使用UIDatePicker(s) 进行输入。一个是“From”日期,另一个是“To”日期,所以这似乎是一个相当常见的场景。
问题在于,当一个字段的 DatePicker 处于活动状态时,用户可能会点击屏幕上的另一个字段。活动的 DatePicker 仍然与第一个字段相关联,因此 UI 让用户感到困惑,因为光标在另一个字段中闪烁,但输入并没有转到那里。
我认为正确的 UI 解决方案是防止用户点击任何其他字段,直到 DatePicker 被解除。但是我无法找到一种方法来检测 firstResponder 正在更改或暂时禁用其他字段的编辑。
这是我当前的代码没有做我需要做的事情:
class AddTripLocationVC: UIViewController, UITextFieldDelegate {
@IBOutlet private weak var tripLocFromDateInput: UITextField!
@IBOutlet private weak var tripLocToDateInput: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
//set up datepickers for text field inputs
createDatePicker(forDateField: tripLocFromDateInput)
createDatePicker(forDateField: tripLocToDateInput)
}
//automatically update the label fields when the date vairables are updated by the UIDatePicker
var locFromDate: Date? {
didSet {
guard locFromDate != nil else { return }
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMM yyyy"
tripLocFromDateInput.text = dateFormatter.string(from: locFromDate!)
}
}
var locToDate: Date? {
didSet {
guard locToDate != nil else { return }
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMM yyyy"
tripLocFromDateInput.text = dateFormatter.string(from: locToDate!)
//Comment after solution found...The problem was the line above
//It should be:
tripLocToDateInput.text = dateFormatter.string(from: locToDate!)
}
}
func createDatePicker(forDateField dateField: UITextField) {
let datePickerView = UIDatePicker()
datePickerView.datePickerMode = .date
dateField.inputView = datePickerView
datePickerView.addTarget(self, action: #selector(handleDatePicker(sender:)), for: .valueChanged)
let doneButton = UIBarButtonItem.init(title: "Done", style: .done, target: self, action: #selector(self.datePickerDone))
let toolBar = UIToolbar.init(frame: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 44))
toolBar.setItems([UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil), doneButton],
animated: true)
dateField.inputAccessoryView = toolBar
}
@objc
func handleDatePicker(sender: UIDatePicker) {
if tripLocFromDateInput.isFirstResponder {
locFromDate = sender.date
} else {
if tripLocToDateInput.isFirstResponder {
locToDate = sender.date
} else {
print("Error: Can't find first responder field.")
}
}
}
@objc
func datePickerDone(dateField: UITextView) {
if tripLocFromDateInput.isFirstResponder {
tripLocFromDateInput.resignFirstResponder()
} else {
if tripLocToDateInput.isFirstResponder {
tripLocToDateInput.resignFirstResponder()
} else {
print("Error: Can't find first responder field.")
}
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldDidEndEditing(_ textField: UITextField) {
textField.becomeFirstResponder()
}
}
对于 iOS 中这种类型的“从”和“到”日期字段,用户界面是否有“标准”方法?
【问题讨论】:
-
为什么在
textFieldDidEndEditing中设置textField.becomeFirstResponder()!!! -
在下面查看我与 ekscrypto 的交流。正如您预期的那样,这不起作用。问题是什么会起作用?
-
@ekscrypto 您的工作代码帮助我意识到我的问题实际上是由 handleDatePicker() 更新的两个日期变量。他们错误地更新了同一个字段,这使得 UI 行为错误(相应地在上面进行了评论)。我还看到,即使焦点发生变化,未关闭的 DatePicker 也会更新焦点所在的任何字段,因此即使用户点击另一个字段,用户界面实际上也不会令人困惑。
-
@Asad Ali Choudhry 请参阅 ekscrypto 已接受答案下方的评论。您还建议的方法无效,但他随后的工作代码有效。这使我意识到我的相关代码也在工作,问题实际上出在 DatePickers 更新的日期变量之一的 didSet{ } 中。我已经在上面显示了该代码(我最初发布时认为它不相关),并接受了 ekscrypto 的解决方案,因为他的代码也可以正常工作。
标签: swift uidatepicker