Я создаю TextField для номера телефона. Но у меня есть проблема: мне нужно запретить пользователям редактировать его из любого места, а не из конца строки.
Я попытался сбросить курсор, используя «Touch up Inside», но он кажется отключенным для TextField.
Есть ли способ ограничить возможные позиции каретки?
Проблема в том, что это портит мой код, который форматирует номер телефона. Если у вас есть другие хорошие способы отформатировать его без этой проблемы (мне нужно, чтобы строка выглядела именно так: +7 (123) 456-78-90, а не иначе), буду признателен за вашу помощь.
private static var prev_phone: String = ""
@IBAction func phoneFieldTextChanged(_ sender: Any){
if let phone = phone_field.text{
if (phone.count <= 4){
phone_field.text = "+7 ("
}
else{
if phone.count > RegistrationViewController.prev_phone.count{
if (phone.count == 7){
phone_field.text! += ") "
}
if (phone.count == 12){
phone_field.text! += "-"
}
if (phone.count == 15){
phone_field.text! += "-"
}
if (phone.count > 18){
phone_field.text = String(phone.prefix(18))
}
}
if phone.count < RegistrationViewController.prev_phone.count{
if (phone.count == 8){
phone_field.text! = String(phone.prefix(6))
}
if (phone.count == 12){
phone_field.text! = String(phone.prefix(11))
}
if (phone.count == 15){
phone_field.text! = String(phone.prefix(14))
}
if (phone.count > 18){
phone_field.text = String(phone.prefix(18))
}
}
}
}
else{
phone_field.text = "+7 ("
}
RegistrationViewController.prev_phone = phone_field.text!
}
В этом случае зачем использовать UITextField? Например, вы можете создать собственную клавиатуру, используя только цифру и кнопку удаления. Пользователь может только ввести число или удалить его. вы можете добавить введенную цифру в форматированную строку.
Назначьте этот класс своему текстовому полю, чтобы пользователи не могли редактировать его из любого места.
class RestrictionTextField: UITextField {
override func closestPosition(to point: CGPoint) -> UITextPosition? {
let beginning = self.beginningOfDocument
let end = self.position(from: beginning, offset: self.text?.count ?? 0)
return end
}
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(UIResponderStandardEditActions.copy(_:)) || action == #selector(UIResponderStandardEditActions.select(_:)) || action == #selector(UIResponderStandardEditActions.cut(_:)) || action == #selector(UIResponderStandardEditActions.paste(_:)) || action == #selector(UIResponderStandardEditActions.selectAll(_:)){
return false
}
else {
return super.canPerformAction(action, withSender: sender)
}
}
}
Для вашего текстового поля вы можете использовать это простое решение.
let kPhonePattern = "+# (###) ###-##-##"
let kPhonePatternReplaceChar: Character = "#"
extension String {
var digits: String {
return String(filter(("0"..."9").contains))
}
func applyPatternOnNumbers(pattern: String = kPhonePattern, replacmentCharacter: Character = kPhonePatternReplaceChar) -> String {
var pureNumber = self.replacingOccurrences( of: "[^0-9]", with: "", options: .regularExpression)
for index in 0 ..< pattern.count {
guard index < pureNumber.count else { return pureNumber }
let stringIndex = String.Index(encodedOffset: index)
let patternCharacter = pattern[stringIndex]
guard patternCharacter != replacmentCharacter else { continue }
pureNumber.insert(patternCharacter, at: stringIndex)
}
return pureNumber
}
}
Использование:
@IBAction func phoneFieldTextChanged(_ sender: UITextField){
sender.text = sender.text?.applyPatternOnNumbers()
}
Инициализатор строки не требуется. filter
применяется к строке, возвращает строку. var digits: String { filter(("0"..."9").contains) }
. Кстати, почему вы добавили это свойство и не использовали его? var pureNumber = digits
@LeoDabus Я добавил, если вам нужно получить цифру из текстового поля (с шаблоном), тогда это полезно. Он возвращает только цифры. И спасибо за поправку фильтра.
Вау, оба решения действительно делают то, для чего они предназначены. Большое спасибо, что потратили время на такой тупой вопрос)