Ios 如何实现在UITextField中输入DOB的功能

Ios 如何实现在UITextField中输入DOB的功能,ios,swift,uitextfield,Ios,Swift,Uitextfield,我使用了一个变量来存储输入的文本,并通过附加剩余后缀“mm/dd/yyyy”对其进行修改。我获得了功能,但如果我尝试将光标更新到正确的位置,就会产生问题。 我使用textfield.selectedTextRange将光标从EOF移动到我需要的位置。但是,它将用“mm/dd/yyyy”中最后一个“y”替换输入的文本。因此,如果我输入“12”,文本将从mm/dd/yyyy变为“yy/mm/yyyy”,而不是“12/dd/yyy” 我做错了吗 let dobPlaceholderText = &qu

我使用了一个变量来存储输入的文本,并通过附加剩余后缀“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(uu:shouldChangeCharactersIn:replacementString:)
在此类用例中非常有前景

该过程可能如下所示:

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
}
  • 确定用户输入后的结果文本,并过滤掉所有非数字字符
  • 应用
    文本中定义的模式
  • 在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
}
private func filtered(uutext:String?,范围:NSRange,替换:String)->Array{
将textFieldText:NSString=(text???)设为NSString
让textAfterUpdate=textFieldText.replacingCharacters(在:范围内,带:替换)
var filtered=数组(textAfterUpdate.filter(validInput.contains))
如果filtered.count>=dobPlaceholder text.count{
过滤=数组(过滤[0..String{
var结果=模式
var iter=filtered.makeIterator()
对于0..Int中的i{
var newPos=0
如果我是空的{
newPos=范围位置
}
否则{
newPos=min(range.location+range.length+1,文本.count)
如果newPos
演示


我们不知道您是否做得不对,因为您没有显示您正在做的事情。请显示实际代码。这比仅仅谈论它要好得多。抱歉@matt。gif没有立即上载。现在是。请选中。这样做不会更好吗?@matt我只能在文本输入完成后更新文本和修改光标。我也可以这样做不要在
shouldChangeCharactersIn:replacementString:)中使用
textField(uu1;:shouldChangeCharactersIn:replacementString:)
您可以像这样获得更新的文本:
let updatedString=(textField.text作为NSString?).replacingCharacters(in:range,with:string)