【问题标题】:Formatting secure text entry by inserting visible spaces通过插入可见空格来格式化安全文本输入
【发布时间】:2016-11-19 00:00:24
【问题描述】:

我希望用户输入格式为 ••• •• •••• 的社会安全号码。 用户键入前 3 个数字,然后我手动附加一个空格。然后他们再输入 2 个数字,我手动添加一个空格。当然,即使是空格也显示为 •。有没有一种本地方法来改变这种行为?我目前正在使用一个时髦的手动实现。

【问题讨论】:

  • AFAIK,没有启用secureTextEntry的本地方法来实现这一点,但您可以通过覆盖UITextFieldDelegate属性的shouldChangeCharactersInRange来实现该行为,但这需要您禁用secureTextEntry
  • 乔恩,请考虑接受其中一个,因为我们未来的访问者无法分辨哪一个帮助了您(我们不想浪费时间尝试使用那些不起作用的)。

标签: ios user-interface cocoa-touch user-input


【解决方案1】:

如果您使用三个不同的文本条目而不是空格,该怎么办?那么当每个用户输入前三个字符时,你跳转到第二个文本输入吗?当他再输入两个时,您跳到第三个文本条目。

这是一个例子:

编辑:现在支持退格(感谢@triple-s)。

extension ViewController: UITextFieldDelegate {

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        switch textField {
            // Jump forwards
        case self.textField1 where string.characters.count == 3 :
            self.textField2.becomeFirstResponder()
        case self.textField2 where string.characters.count == 2 :
            self.textField3.becomeFirstResponder()

            // Jump backwards
        case self.textField3 where string.characters.count == 0 :
            self.textField2.becomeFirstResponder()
        case self.textField2 where string.characters.count == 0 :
            self.textField1.becomeFirstResponder()
        default :
            break
        }

        return true
    }
}

【讨论】:

  • @JonSetting for back space 你可以检查文本框是否为空然后将前一个文本框设置为firstResponser
  • 这是在正确的轨道上,但 string 只是新输入:它的长度为 1。您需要检查建议范围的位置。第二部分几乎是错误的:textField:shouldChangeCharactersInRange:replacementString: isn't called 用于文本字段开头的退格。
  • 这是一个很好的解决方案,可以帮助其他人。但我刚刚意识到我不能使用它,因为文本对齐必须居中。
  • 真的有人读过或运行过这段代码吗?! 它不工作如所写。这个想法是合理的,但它没有在这段代码中实现。 @JonSetting
  • 这不是建议解决方案的正确实现。
【解决方案2】:

这可以按照要求在一个文本字段中实现。我只在 gif 中点击了“1”。

  1. 您选择键盘类型为数字(0-9),这样可以确保输入的所有内容都是数字。

  2. 那么就可以采用textField委托,实现委托方法

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { 打印(字符串)

    let  char = string.cStringUsingEncoding(NSUTF8StringEncoding)!
    let isBackSpace = { return strcmp(char, "\\b") == -92}
    
    if (textField.text?.characters.count == 3 && !isBackSpace()) || (textField.text?.characters.count == 6 && !isBackSpace()){
        textField.text = textField.text! + " "
    }
    
    if (textField.text?.characters.count) == 11 && !isBackSpace(){
        ssnString = textField.text!
        self.view.endEditing(true)
    
    }
    
    return true
    

    }

如果你没有退格,这包括在第三位之后添加空格的逻辑,并且对于第六位之后的数字也是如此。

另外,用户输入 11 位后,作为 SSN 的格式,将不允许用户输入更多的数字,输入 11 位后,SSN 保存在 ssnString 中,用于特殊屏蔽。

  1. 因为你不想屏蔽空格,所以我们不能使用secureTextEntry。所以在 didEndEditing 中,我给出了一个条件,只有当用户输入完整的 SSN 时,我们才会屏蔽它,如果你愿意,可以修改为任何场景。但我认为这更有意义。

func textFieldDidEndEditing(textField: UITextField) { if textField.text?.characters.count == 11 { maskSSNTextField() } }

在 maskSSNTextField 方法中, func maskSSNTextField() { textField.text = "••• •• ••••" }

  1. 最后,如果用户想要更改文本,我们需要在用户返回时取消屏蔽它

func textFieldDidBeginEditing(textField: UITextField) { if textField.text == "••• •• ••••"{ textField.text = ssnString } }

这完全满足您的要求。如果您还有其他问题,请告诉我。

【讨论】:

  • 但它应该是一个安全的文本字段,我可以清楚地看到你输入的整个数字。这不是安全文本的目的。安全文本仅在很短的时间内显示您输入的最后一个数字。
  • 如果您将其设置为安全,该空间也将被屏蔽。如果字符串 != " "
【解决方案3】:

我更改了 didChangeInRange 方法以满足您的新要求,尽管我认为我之前的答案可能有效。现在它就像在 gif 中一样工作。如果您希望它仍然被屏蔽,您可以更改 textField 中的代码确实开始编辑。

   func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

    let  char = string.cStringUsingEncoding(NSUTF8StringEncoding)!
    let isBackSpace = { return strcmp(char, "\\b") == -92}

    if (textField.text?.characters.count == 3 && !isBackSpace()) || (textField.text?.characters.count == 6 && !isBackSpace()){
        textField.text = textField.text! + " "
        ssnString = ssnString + " "
    }



    if isBackSpace() {

        ssnString = ssnString.substringToIndex(ssnString.endIndex.predecessor())

    }else {

        ssnString = ssnString + string
        print(ssnString)

        if ssnString.characters.count >= 2 {
            var starString = ""
            for i in 0...ssnString.characters.count-2 {

                if i==3 || i==6 {
                    starString = starString+" "
                }else {
                    starString = starString+"•"
                }
            }
            textField.text = ""
            print(ssnString.characters.last)
            textField.text = starString
        }
    }

    if (textField.text?.characters.count) == 11 && !isBackSpace(){
        self.view.endEditing(true)

    }
    return true
}

【讨论】:

  • 如果您有其他疑问,请告诉我。
  • 不要发布另一个答案,而是编辑您已经写过的答案。
【解决方案4】:

我一直在使用的简单解决方案是将输入字符串转换为 NSAttributedString,并在适当的位置添加文本间距 (.kern) 属性,并将 isSecureTextEntry 设置为 true。 禁用 isSecureTextEntry 并手动执行,除了过于复杂之外,至少在有人使用第三方键盘时可能会产生安全隐患。

var ssnText = "123456789"

let spacerPositions = [ 2, 4 ]
let spacingAmount: CGFloat = 5.0

let spacerRanges:[NSRange] = spacerPositions
                                .filter { $0 < ssnText.count - 1 }
                                .map { NSRange(location: $0, length: 1) }

let attributedString = NSMutableAttributedString(string: ssnText)
for range in spacerRanges {
    attributedString.addAttribute(.kern, value: spacingAmount, range: range)
}

textField.attributedText = attributedString

textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) 中调用这些东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-17
    • 2022-08-18
    • 1970-01-01
    • 2021-05-08
    • 2016-05-14
    • 1970-01-01
    相关资源
    最近更新 更多