使 UITextfield 仅接受片假名字符 - swift

Make UITextfield accept only Katakana characters - swift

我希望我的 UITextField 只接受 一个字符,它应该是一个 片假名字符。当用户使用 Japanese-Romaji 拼音键盘输入时,我该怎么做?

General->Keyboard->Keyboards-> Japanese Romaji

以下代码不起作用,因为我将英文字符输入 string 参数。看来我必须处理 textFiled 的 markedTextRange 属性,但不确定如何处理。知道如何修改以下方法来满足我的要求吗?

Multistage text input is a requirement when the language is ideographic and the keyboard is phonetic.

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if string.rangeOfCharacter(from: .init(charactersIn: "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン")) != nil || string == ""{
            return true
        } else {
            return false
        }
    }

根据我的观察,markedTextRange 直到 shouldChangeCharactersInRange 被调用后才会更新。假设我输入 s,首先调用 shouldChangeCharactersInRange,然后更新 markedTextRange。这意味着很难区分“在英文键盘上输入第一个 's'”和“在罗马字键盘上输入第一个 's'”,我们希望禁止前者。在这两种情况下,markedTextRangeshouldChangeCharactersInRange.

中为零

因此,我认为如果您改为 editingChanged 会更容易:

textfield.addTarget(self, action: #selector(textFieldChanged), for: .editingChanged)

...

let katakanas =
    "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン"
@objc func textFieldChanged() {
    let newString = textfield.text ?? ""
    if !(newString.count == 1 &&
            katakanas.contains(newString.first!)) && textfield.markedTextRange == nil {
        // perhaps show an error alert here too
        textfield.text = ""
    }
}

只有在文本更改和 markedTextRange 更新后才会调用此方法,因此 textfield.markedTextRange == nil 检查将正常工作。将整个文本字段设置为空白,以防用户输入无效内容,这对用户体验来说应该不算太糟糕,因为无论如何你只想接受一个字符。

您仍然可以使用 shouldChangeCharactersInRange 来防止用户在已经有一个片假名后输入更多字母:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if let firstChar = textField.text?.first,
       katakanas.contains(firstChar) && string != "" {
        return false
    }
    return true
}