我有一个 textField,我不想在其中允许前导空格。因此,我实现了 textField(textField:shouldChangeCharactersInRange:replacementString:) 并阻止尝试将文本更改为以空格开头的内容。这按预期工作。

不幸的是,这弄乱了 QuickType。每次我在一个空字段中按下空格,然后我的 textField 会忽略它,Quicktype 文本就会以这个空格为前缀。更清楚地说,QuickType 将插入的文本带有前缀,额外的空格未显示在 QuickType 栏的 UI 中。

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let currentText = textField.text as NSString
    let proposedText = currentText.stringByReplacingCharactersInRange(range, withString: string)
    if !proposedText.isEmpty {
        let firstCharacterString = String(proposedText[proposedText.startIndex]) as NSString
        if firstCharacterString.rangeOfCharacterFromSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).location == 0 {
            println("starts with whitespace \"\(proposedText)\"")
            return false
        }
    }
    return true
}

这是一些日志记录,以查看当我按空格 5 次然后按 I'm QuickType 建议时发生了什么:
starts with whitespace " "           // pressing space key
starts with whitespace " "
starts with whitespace " "
starts with whitespace " "
starts with whitespace " "
starts with whitespace "     I'm"    // Inserted by QuickType after pressing the "I'm" suggestion
starts with whitespace " "           // Inserted by QuickType as well

通过检查该委托(delegate)方法中的变量,我可以验证问题确实出在我从 UITextField 获得的替换字符串上。它已经包含以空格为前缀的建议。

有谁知道我如何防止这种情况发生,或者我如何“重置”QuickType 建议?

一种解决方法是从多字符插入中修剪空格,但首先我想看看我是否缺少一种以干净的方式处理问题的方法。

最佳答案

通过更多的测试,我得出结论,这是一个错误。

首先我认为键盘和 QuickType 是从 UITextField 解耦的。但事实并非如此。在填充的 textField 中更改光标的位置实际上会更改快速输入建议。所以 textField 实际上与 quicktype 通信。

所以我提交了一个错误。

Apple 的错误:rdar://19250739
OpenRadar 的错误:5794406481264640

如果有人对解决方法感兴趣:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let currentText = textField.text as NSString
    let proposedText = currentText.stringByReplacingCharactersInRange(range, withString: string)

    if proposedText.hasPrefix(" ") {
        // Don't allow space at beginning
        println("Ignore text \"\(proposedText)\"")

        // workaround
        if textField.text == "" && countElements(string) > 1 {
            // multi insert into empty field. probably from QuickType
            // so we should strip whitespace and set new text directly
            let trimmedString = proposedText.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
            println("Inserted \"\(trimmedString)\" with Quicktype. ")
            textField.text = trimmedString
        }

        return false
    }
    return true
}

10-08 09:36