Максимальная длина UITextField
Когда я пробовал Как установить максимальное количество символов, которые можно ввести в UITextField с помощью быстрого?, я увидел, что если я использую все 10 символов, я тоже не могу стереть символ.
Единственное, что я могу сделать, это отменить операцию (удалить все символы вместе).
Кто-нибудь знает, как не блокировать клавиатуру (чтобы я не мог добавлять другие буквы/символы/цифры, но я могу использовать backspace)?
В Swift 5 и iOS 12 попробуйте следующую реализацию метода textField(_:shouldChangeCharactersIn:replacementString:)
который является частью протокола UITextFieldDelegate
:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
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 <= 10
}
- Наиболее важной частью этого кода является преобразование
range
(NSRange
) вrangeOfTextToReplace
(Range<String.Index>
). Посмотрите этот видеоурок, чтобы понять, почему это преобразование важно. - Чтобы этот код работал правильно, вы также должны установить значение
textField
smartInsertDeleteType
вUITextSmartInsertDeleteType.no
. Это предотвратит возможную вставку (нежелательного) дополнительного пространства при выполнении операции вставки.
Полный пример кода ниже показывает, как реализовать textField(_:shouldChangeCharactersIn:replacementString:)
в UIViewController
:
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var textField: UITextField! // Link this to a UITextField in Storyboard
override func viewDidLoad() {
super.viewDidLoad()
textField.smartInsertDeleteType = UITextSmartInsertDeleteType.no
textField.delegate = self
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
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 <= 10
}
}
Я делаю это так:
func checkMaxLength(textField: UITextField!, maxLength: Int) {
if (countElements(textField.text!) > maxLength) {
textField.deleteBackward()
}
}
Код работает для меня. Но я работаю с раскадрой. В Storyboard я добавляю действие для текстового поля в контроллере представления в редактировании изменено.
Связанные вопросы
Похожие вопросы
Обновление для Swift 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else { return true }
let newLength = text.count + string.count - range.length
return newLength <= 10
}
Добавить более подробно из ответа @Martin
// linked your button here
@IBAction func mobileTFChanged(sender: AnyObject) {
checkMaxLength(sender as! UITextField, maxLength: 10)
}
// linked your button here
@IBAction func citizenTFChanged(sender: AnyObject) {
checkMaxLength(sender as! UITextField, maxLength: 13)
}
func checkMaxLength(textField: UITextField!, maxLength: Int) {
// swift 1.0
//if (count(textField.text!) > maxLength) {
// textField.deleteBackward()
//}
// swift 2.0
if (textField.text!.characters.count > maxLength) {
textField.deleteBackward()
}
}
В Swift 4
10 символов ограничивают текстовое поле и позволяют удалить (возврат)
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == userNameFTF{
let char = string.cString(using: String.Encoding.utf8)
let isBackSpace = strcmp(char, "\\b")
if isBackSpace == -92 {
return true
}
return textField.text!.count <= 9
}
return true
}
func checkMaxLength(textField: UITextField!, maxLength: Int) {
if (textField.text!.characters.count > maxLength) {
textField.deleteBackward()
}
}
небольшое изменение для IOS 9
Swift 3
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let nsString = NSString(string: textField.text!)
let newText = nsString.replacingCharacters(in: range, with: string)
return newText.characters.count <= limitCount
}
Если вы хотите перезаписать последнюю букву:
let maxLength = 10
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if range.location > maxLength - 1 {
textField.text?.removeLast()
}
return true
}
Я разместил решение с помощью IBInspectable
, поэтому вы можете изменить максимальное значение длины как в построителе интерфейса, так и программно. Проверьте здесь
Остерегайтесь ошибки отмены UITextField, упомянутой в этом сообщении: Задайте максимальную длину символа UITextField
вот как вы его исправите быстрым
if(range.length + range.location > count(textField.text)) {
return false;
}
Here is my version of code. Hope it helps!
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let invalidCharacters = NSCharacterSet(charactersInString: "0123456789").invertedSet
if let range = string.rangeOfCharacterFromSet(invalidCharacters, options: nil, range:Range<String.Index>(start: string.startIndex, end: string.endIndex))
{
return false
}
if (count(textField.text) > 10 && range.length == 0)
{
self.view.makeToast(message: "Amount entry is limited to ten digits", duration: 0.5, position: HRToastPositionCenter)
return false
}
else
{
}
return true
}
Я использую этот протокол/расширение в одном из моих приложений, и он немного читаем. Мне нравится, как он распознает обратные пространства и явно сообщает вам, когда символ является backspace.
Некоторые вещи, которые следует учитывать:
1. В любом случае это расширение протокола должно указывать ограничение символа. Обычно это будет ваш ViewController, но вы можете реализовать ограничение символа как вычисленное свойство и вернуть что-то еще, например лимит символов на одной из ваших моделей.
2. Вам нужно будет вызвать этот метод внутри вашего текстового поля shouldChangeCharactersInRange метод делегата. В противном случае вы не сможете заблокировать ввод текста, вернув false и т.д.
3. Вероятно, вы захотите разрешить обратные символы.. Поэтому я добавил дополнительную функцию для обнаружения обратных пространств. Ваш метод shouldChangeCharacters может проверить это и вернуть "истина" на раннем этапе, чтобы вы всегда разрешали backspaces.
protocol TextEntryCharacterLimited{
var characterLimit:Int { get }
}
extension TextEntryCharacterLimited{
func charactersInTextField(textField:UITextField, willNotExceedCharacterLimitWithReplacementString string:String, range:NSRange) -> Bool{
let startingLength = textField.text?.characters.count ?? 0
let lengthToAdd = string.characters.count
let lengthToReplace = range.length
let newLength = startingLength + lengthToAdd - lengthToReplace
return newLength <= characterLimit
}
func stringIsBackspaceWith(string:String, inRange range:NSRange) -> Bool{
if range.length == 1 && string.characters.count == 0 { return true }
return false
}
}
Если кто-то из вас интересуется, у меня есть репозиторий Github, где я взял некоторые из этих правил поведения персонажа и поместил его в iOS. Там протокол, который вы можете реализовать, чтобы отобразить лимит символов на Twitter, показывает, насколько вы прошли выше лимита символов.
Поскольку делегаты являются отношениями 1 к 1, и я могу использовать его в другом месте по другим причинам, мне нравится ограничивать длину текстового поля, добавляя этот код в свою установку:
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
setup()
}
required override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
// your setup...
setMaxLength()
}
let maxLength = 10
private func setMaxLength() {
addTarget(self, action: #selector(textfieldChanged(_:)), for: UIControlEvents.editingChanged)
}
@objc private func textfieldChanged(_ textField: UITextField) {
guard let text = text else { return }
let trimmed = text.characters.prefix(maxLength)
self.text = String(trimmed)
}
Вы можете использовать в Swift 5 или Swift 4, как изображение выглядит как ниже
- Добавить textField в View Controller
- Подключиться к тексту в ViewController
добавить код в представление ViewController
class ViewController: UIViewController , UITextFieldDelegate { @IBOutlet weak var txtName: UITextField! var maxLen:Int = 8; override func viewDidLoad() { super.viewDidLoad() txtName.delegate = self } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { if(textField == txtName){ let currentText = textField.text! + string return currentText.count <= maxLen } return true; } }
Вы можете скачать полную исходную форму GitHub: https://github.com/enamul95/TextFieldMaxLen
Вам нужно проверить, будет ли существующая строка плюс вход больше 10.
func textField(textField: UITextField!,shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
NSUInteger newLength = textField.text.length + string.length - range.length;
return !(newLength > 10)
}
Посмотрите другие вопросы по меткам max ios uitextfield swift character или Задайте вопрос