Форматирование защищенного ввода текста путем вставки видимых пробелов

Я хочу, чтобы пользователь вводил номер социального страхования в формате •••••••••. Пользователь вводит первые 3 числа, затем я добавляю пробел вручную. Затем они вводят еще 2 числа, и я вручную добавляю пробел. Конечно, даже пробелы отображаются как •. Есть ли собственный способ изменить это поведение? В настоящее время я использую фанк-ручную реализацию этого.

Ответ 1

Что, если вместо пробелов вы используете три разных текстовых ввода? Затем, когда каждый пользователь вводит первые три символа, вы переходите ко второй текстовой записи? Когда он набирает еще два, вы переходите к третьей текстовой записи.

Вот пример:

EDIT: Теперь поддерживает backspace (благодаря @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
    }
}

Ответ 2

Это может быть достигнуто в одном текстовом поле по запросу. Я только постучал "1", в gif.

введите описание изображения здесь

  • Вы выбираете тип вашей клавиатуры, чтобы быть номером (0-9), который может обеспечить все, что будет введено, только номер.

  • Затем вы можете принять делегат textField и реализовать метод делегата

    func textField (textField: UITextField, shouldChangeCharactersInRange: 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
    

    }

Это включает в себя логику добавления пространства после третьей цифры, если вы не занимаете обратную позицию, и то же самое для 6-й цифры.

Кроме того, после ввода пользователем 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 с атрибутами text spacing (.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).