Как применить формат при вводе UITextField

#ios #swift

#iOS #swift

Вопрос:

Я хотел бы применить этот формат при вводе в UITextField

Формат: XXX-XXXXXXXXX-X-XX

У меня уже есть этот формат ‘XXXX XXXX XXXX XXXX’, который был выполнен следующим образом, это также работает, когда я стираю цифры.

 class LoginViewController: UIViewController {

@IBOutlet weak var cardTextField: UITextField!
private var isErasingTextField: Bool! = false

 override func viewDidLoad() {
 super.viewDidLoad()

  cardTextField.delegate = self
  cardTextField.addTarget(self, action: #selector(didChangeText(textField:)), for: .editingChanged)


 }

 @objc func didChangeText(textField: UITextField) {
    if let selectedRange = textField.selectedTextRange {
        let position = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start)
        /// This method is the mask to set format
        textField.cardstringFormat(positionOfEditing: position, erasing: isErasingTextField)
    }
 }


extension LoginViewController: UITextFieldDelegate {

  public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
    /// Important isErasingTextField
    isErasingTextField = range.length == 0 ? false : true

    guard let textFieldText = textField.text,
        let rangeOfTextToReplace = Range(range, in: textFieldText) else {
            return false
    }
    let substringToReplace = textFieldText[rangeOfTextToReplace]
    let count = textFieldText.count - substringToReplace.count   string.count

    return count <= 15
  }


}
 

Это расширение UITextField:

  extension UITextField { 
  
  /// Method to set card format
  func cardstringFormat(positionOfEditing: Int? = nil, erasing: Bool? = nil) {
    guard let text = text else {return}
    let trimmedString = text.components(separatedBy: .whitespaces).joined()

    let arrOfCharacters = Array(trimmedString)
    var modifiedCreditCardString = ""
    if !arrOfCharacters.isEmpty {

        for iterator in 0..<arrOfCharacters.count {
            modifiedCreditCardString.append(arrOfCharacters[iterator])
            if (iterator   1) % 4 == 0 amp;amp; iterator   1 != arrOfCharacters.count {
                modifiedCreditCardString.append(" ")
            }
        }
    }
    self.text = modifiedCreditCardString
    if positionOfEditing != nil {
        if positionOfEditing!%5 == 0 amp;amp; positionOfEditing! != 0 {
            setCursor(position: positionOfEditing!   (erasing! ? -1 : 1))
        } else {
            setCursor(position: positionOfEditing!)
        }
    }
}

  func setCursor(position: Int) {
     if let text = text, (text.count - 1) > position { }
     let position = self.position(from: beginningOfDocument, offset: position)!
     selectedTextRange = textRange(from: position, to: position)

  }

 }
 

Как я могу отредактировать этот метод или создать новый, чтобы получить этот формат, о котором я упоминал ранее:
XXX-XXXXXXXXX-X-XX

Комментарии:

1. Я не думаю, что стоит сохранять позицию курсора при вводе номера кредитной карты (или карточки входа). Просто реализуйте метод deleteBackward и удалите последнюю цифру. Пользователь всегда может повторно ввести цифры слева направо.

2. О, я понимаю. Как я могу отредактировать этот метод, чтобы получить формат, который я ищу? XXX-XXXXXXXXX-X-XX

Ответ №1:

Я не думаю, что стоит сохранять позицию курсора при вводе номера кредитной карты (или карточки входа). Просто реализуйте метод deleteBackward и удалите последнюю цифру. Пользователь всегда может повторно ввести цифры слева направо. Я бы также подкласс textfield и создать настраиваемое поле. Итак, сначала удалите все не цифры из поля, а затем измените количество оставшихся цифр. Если есть от 3 до 11, просто вставьте первый дефис. Если их 12, вставьте первый и второй дефисы. Если есть 13, добавьте также третий дефис. Не забудьте вставить их в обратном порядке, чтобы упростить вашу жизнь:

 class LoginField: UITextField {
    override func didMoveToSuperview() {
        keyboardType = .numberPad
        textAlignment = .center
        autocorrectionType = .no
        addTarget(self, action: #selector(editingChanged), for: .editingChanged)
    }
    override func deleteBackward() {
        text?.removeAll(where: .isDigit.negated)
        let _ = text?.popLast()
        sendActions(for: .editingChanged)
    }
}
 

 extension LoginField {
    @objc func editingChanged(_ textField: UITextField) {
        text?.removeAll(where: .isDigit.negated)
        text = text?.prefix(15).string
        if let offset = text?.count,
           let startIndex = text?.startIndex {
            switch offset {
            case 3...11:
                if let index = text?.index(startIndex, offsetBy: 3) {
                    text?.insert("-", at: index)
                }
            case 12:
                if let index = text?.index(startIndex, offsetBy: 12) {
                    text?.insert("-", at: index)
                }

                if let index = text?.index(startIndex, offsetBy: 3) {
                    text?.insert("-", at: index)
                }
            case 13...15:
                if let index = text?.index(startIndex, offsetBy: 13) {
                    text?.insert("-", at: index)
                }
                if let index = text?.index(startIndex, offsetBy: 12) {
                    text?.insert("-", at: index)
                }
                if let index = text?.index(startIndex, offsetBy: 3) {
                    text?.insert("-", at: index)
                }
            default: break
            }
        }
    }
}
 

 extension Bool {
    var negated: Bool { !self }
}
 

 extension LosslessStringConvertible {
    var string: String { .init(self) }
}
 

 extension Character {
    var isDigit: Bool { "0"..."9" ~= self }
}
 

Комментарии:

1. Спасибо за вашу помощь, Лео. Ваш метод добавления «-» работает правильно. На самом деле это не UITextField, который я использую, это пользовательское UITextField, созданное банковской компанией. Когда я пытаюсь создать пользовательский класс UITextField, он не работает, потому что я не могу получить доступ к этому пользовательскому UITextField (созданному банковской компанией). Я думаю, это проблема, почему я не могу удалить «-» в моем customtextfield, потому что я не проверил метод ‘deleteBackward’: (Как вы думаете, есть ли другой способ сделать это? Я имею в виду удаление символов «-«?