Я хочу, чтобы пользователь вводил номер социального страхования в формате •••••••••. Пользователь вводит первые 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, который будет использоваться для специальной маскировки.
- Поскольку вы не хотите маскировать пространство, мы не можем использовать secureTextEntry. Таким образом, в didEndEditing я дал условие только в том случае, если пользователь вводит полный SSN, мы замаскируем его, который может быть изменен для любого сценария, если вы хотите. Но я думаю, что это имеет больше смысла.
func textFieldDidEndEditing(textField: UITextField) {
if textField.text?.characters.count == 11 {
maskSSNTextField()
}
}
В методе maskSSNTextField,
func maskSSNTextField() {
textField.text = "••• •• ••••"
}
- Наконец, нам нужно разобрать его, когда пользователь вернется к нему, если они захотят изменить текст
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)
.