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

Posted

技术标签:

【中文标题】使 UITextfield 只接受片假名字符 - swift【英文标题】:Make UITextfield accept only Katakana characters - swift 【发布时间】:2021-05-19 06:03:28 【问题描述】:

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

General->Keyboard->Keyboards-> Japanese Romaji

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

当语言是表意而键盘是拼音时,需要多级文本输入。

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

【问题讨论】:

我注意到您的列表中没有包含所有片假名,例如带有゛和゜的片假名,以及ヤ、yu、ヨ、ツ的小版本(即ャ、ュ、ョ,ッ) 这是故意的吗? 我从我的客户那里得到了上面的字符列表,我们将它们用于我们应用程序中非常具体的绘图功能。所以我希望我们不需要考虑小版本。感谢您注意到????‍♂️ 【参考方案1】:

根据我的观察,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 检查将正常工作。将整个文本字段设置为空白以防用户输入无效的内容,这对 UX 来说应该不算太糟糕,因为无论如何您只打算接受一个字符。

你仍然可以使用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

【讨论】:

感谢您的回答。我用你的 textFieldChanged() 函数进行了测试。当我用英文键盘输入a 时,textfield.markedTextRange 为零,因此textfield.text = "" 按预期被调用?。但是当我用罗马字键盘输入a 时,textfield.markedTextRange 不是 nil 并且 被插入到 textField 中(这不是片假名)。不知道为什么textfield.markedTextRange 不为零? @S.Basnagoda 这是预期的。 textFieldChanged 仅在您从选项列表中选择一个选项时调用(当您取消标记时)。如果你真的选择键盘顶部的あ选项,あ会消失。您必须允许将 あ 作为“标记文本”输入到文本字段中,否则您将如何在没有 あ 的情况下键入 ア?我的回答是它不允许未标记的非片假名。

以上是关于使 UITextfield 只接受片假名字符 - swift的主要内容,如果未能解决你的问题,请参考以下文章

如何限制 UITextField 在 Swift 中只接受数字?

如何使键盘 UITextField 中的数字视图成为默认值?

Swift:在自动格式化 UITextField 后动画 UIButton

如何使 HTML 输入标签只接受数值?

如何使文本框只接受数字并用逗号格式化数字?

允许在 UITextfield ios 中使用德语 UMLAUT 字符