#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’: (Как вы думаете, есть ли другой способ сделать это? Я имею в виду удаление символов «-«?