如何实现此功能以在 UITextField 中输入 DOB
How can I achieve this functionality to enter DOB in UITextField
我使用一个变量来存储正在输入的文本,并通过附加“mm/dd/yyyy”的剩余后缀来修改它。我获得了功能,但如果我尝试将光标更新到正确的位置,则会产生问题。
我使用 textfield.selectedTextRange 将光标从 EOF 移动到我需要的位置。但是,它正在用“mm/dd/yyyy”中的最后一个“y”替换输入的文本。因此,如果我输入“12”,文本将从 mm/dd/yyyy| 更改为到“yy|/mm/yyyy”而不是“12|/dd/yyy”
我是不是做错了?
let dobPlaceholderText = "mm/dd/yyyy"
var enteredDOBText = ""
@objc func textFieldDidChange(_ textField: UITextField){
enteredDOBText.append(textField.text.last ?? Character(""))
let modifiedText = enteredDOBText + dobPlaceholderText.suffix(dobPlaceholderText.count - enteredDOBText.count)
textField.text = modifiedText
setCursorPosition(input: dob.textField, position: enteredDOBText.count)
}
private func setCursorPosition(input: UITextField, position: Int){
let position = input.position(from: input.beginningOfDocument, offset: position)!
input.selectedTextRange = input.textRange(from: position, to: position)
}
matt 和 aheze 在评论中使用 textField(_:shouldChangeCharactersIn:replacementString:)
的建议在此类用例中非常有前途。
程序可能如下所示:
- 确定用户输入后的结果文本并过滤掉所有 non-numeric 个字符
- 应用您在
dobPlaceholderText
中定义的模式
- 在 UIText 字段中设置结果
- 确定并设置新的光标位置
在源代码中可能如下所示:
let dobPlaceholderText = "mm/dd/yyyy"
let delims = "/"
let validInput = "0123456789"
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
let filteredText = filtered(textField.text, range: range, replacement: string)
let newText = applyPattern(filteredText, pattern: Array(dobPlaceholderText))
textField.text = newText
let newPosition = newCursorPosition(range: range, replacement: string, newText: newText)
setCursorPosition(input: textField, position: newPosition)
return false
}
filtered
、applyPattern
和 newCursorPosition
三种方法的实际实现取决于您想要实现的具体细节行为。这只是一个示例实现,请使用反映您的要求的内容。
private func filtered(_ text: String?,range:NSRange, replacement: String) -> Array<Character> {
let textFieldText: NSString = (text ?? "") as NSString
let textAfterUpdate = textFieldText.replacingCharacters(in: range, with: replacement)
var filtered = Array(textAfterUpdate.filter(validInput.contains))
if filtered.count >= dobPlaceholderText.count {
filtered = Array(filtered[0..<dobPlaceholderText.count])
}
return filtered
}
private func applyPattern(_ filtered: Array<Character>, pattern: Array<Character>) -> String {
var result = pattern
var iter = filtered.makeIterator()
for i in 0..<pattern.count {
if delims.contains(pattern[i]) {
result[i] = pattern[i]
} else if let ch = iter.next() {
result[i] = ch
} else {
result[i] = pattern[i]
}
}
return String(result)
}
private func newCursorPosition(range: NSRange, replacement: String, newText: String) -> Int {
var newPos = 0
if replacement.isEmpty {
newPos = range.location
}
else {
newPos = min(range.location + range.length + 1, dobPlaceholderText.count)
if newPos < dobPlaceholderText.count && delims.contains(Array(newText)[newPos]) {
newPos += 1
}
}
return newPos
}
演示
我使用一个变量来存储正在输入的文本,并通过附加“mm/dd/yyyy”的剩余后缀来修改它。我获得了功能,但如果我尝试将光标更新到正确的位置,则会产生问题。 我使用 textfield.selectedTextRange 将光标从 EOF 移动到我需要的位置。但是,它正在用“mm/dd/yyyy”中的最后一个“y”替换输入的文本。因此,如果我输入“12”,文本将从 mm/dd/yyyy| 更改为到“yy|/mm/yyyy”而不是“12|/dd/yyy”
我是不是做错了?
let dobPlaceholderText = "mm/dd/yyyy"
var enteredDOBText = ""
@objc func textFieldDidChange(_ textField: UITextField){
enteredDOBText.append(textField.text.last ?? Character(""))
let modifiedText = enteredDOBText + dobPlaceholderText.suffix(dobPlaceholderText.count - enteredDOBText.count)
textField.text = modifiedText
setCursorPosition(input: dob.textField, position: enteredDOBText.count)
}
private func setCursorPosition(input: UITextField, position: Int){
let position = input.position(from: input.beginningOfDocument, offset: position)!
input.selectedTextRange = input.textRange(from: position, to: position)
}
matt 和 aheze 在评论中使用 textField(_:shouldChangeCharactersIn:replacementString:)
的建议在此类用例中非常有前途。
程序可能如下所示:
- 确定用户输入后的结果文本并过滤掉所有 non-numeric 个字符
- 应用您在
dobPlaceholderText
中定义的模式
- 在 UIText 字段中设置结果
- 确定并设置新的光标位置
在源代码中可能如下所示:
let dobPlaceholderText = "mm/dd/yyyy"
let delims = "/"
let validInput = "0123456789"
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
let filteredText = filtered(textField.text, range: range, replacement: string)
let newText = applyPattern(filteredText, pattern: Array(dobPlaceholderText))
textField.text = newText
let newPosition = newCursorPosition(range: range, replacement: string, newText: newText)
setCursorPosition(input: textField, position: newPosition)
return false
}
filtered
、applyPattern
和 newCursorPosition
三种方法的实际实现取决于您想要实现的具体细节行为。这只是一个示例实现,请使用反映您的要求的内容。
private func filtered(_ text: String?,range:NSRange, replacement: String) -> Array<Character> {
let textFieldText: NSString = (text ?? "") as NSString
let textAfterUpdate = textFieldText.replacingCharacters(in: range, with: replacement)
var filtered = Array(textAfterUpdate.filter(validInput.contains))
if filtered.count >= dobPlaceholderText.count {
filtered = Array(filtered[0..<dobPlaceholderText.count])
}
return filtered
}
private func applyPattern(_ filtered: Array<Character>, pattern: Array<Character>) -> String {
var result = pattern
var iter = filtered.makeIterator()
for i in 0..<pattern.count {
if delims.contains(pattern[i]) {
result[i] = pattern[i]
} else if let ch = iter.next() {
result[i] = ch
} else {
result[i] = pattern[i]
}
}
return String(result)
}
private func newCursorPosition(range: NSRange, replacement: String, newText: String) -> Int {
var newPos = 0
if replacement.isEmpty {
newPos = range.location
}
else {
newPos = min(range.location + range.length + 1, dobPlaceholderText.count)
if newPos < dobPlaceholderText.count && delims.contains(Array(newText)[newPos]) {
newPos += 1
}
}
return newPos
}
演示