Я знаю, что есть другие темы по этому поводу, но я не могу понять, как это реализовать.
Я пытаюсь ограничить UITextField только 5 символами
Желательно буквенно-цифровые и - и. и _
Я видел этот код
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange,
replacementString string: String) -> Bool
{
let maxLength = 4
let currentString: NSString = textField.text
let newString: NSString =
currentString.stringByReplacingCharactersInRange(range, withString: string)
return newString.length <= maxLength
}
и
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let length = count(textField.text.utf16) + count(string.utf16) - range.length
return length <= 10
}
Я просто не знаю, как на самом деле это реализовать или какое «текстовое поле» мне следует заменить на свое пользовательское с именем UITextField.
String
в Swift в эти дни вы можете , наконец , просто .prefix (п)Ответы:
Ваш контроллер представления должен соответствовать
UITextFieldDelegate
, как показано ниже:class MyViewController: UIViewController, UITextFieldDelegate { }
Установите делегата вашего текстового поля:
myTextField.delegate = self
Реализуйте метод в вашем контроллере представления:
textField(_:shouldChangeCharactersInRange:replacementString:)
Все вместе:
class MyViewController: UIViewController,UITextFieldDelegate //set delegate to class @IBOutlet var mytextField: UITextField // textfield variable override func viewDidLoad() { super.viewDidLoad() mytextField.delegate = self //set delegate } func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let maxLength = 4 let currentString: NSString = textField.text let newString: NSString = currentString.stringByReplacingCharactersInRange(range, withString: string) return newString.length <= maxLength }
Для Swift 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let maxLength = 1 let currentString: NSString = (textField.text ?? "") as NSString let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString return newString.length <= maxLength }
Разрешить ввод только указанного набора символов в данное текстовое поле
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { var result = true if mytextField == numberField { if count(string) > 0 { let disallowedCharacterSet = NSCharacterSet(charactersInString: "0123456789.-").invertedSet let replacementStringIsLegal = string.rangeOfCharacterFromSet(disallowedCharacterSet) == nil result = replacementStringIsLegal } } return result }
Как запрограммировать текстовое поле iOS, которое принимает только числовой ввод с максимальной длиной
источник
textField
в методеfunc textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
shouldChangeCharactersInRange
вызывается обратный вызов , это для всех текстовых полей, вы получаете обратный вызов в одномshouldChangeCharactersInRange
и том же месте, и внутри этого метода вы можете узнать, какое текстовое поле редактируется благодаря переданному параметру, которыйtextField
вы можете, например, дать тег для каждого текстового поля и тест внутриshouldChangeCharactersInRange
и для каждого текстового поля выполняет проверку содержимогоСовременный Свифт
Обратите внимание, что большая часть кода онлайн, посвященного этой проблеме, чрезвычайно устарела .
Вставьте следующее в любой файл Swift в своем проекте. (Вы можете назвать файл как угодно, например "Handy.swift".)
Это, наконец, решает одну из самых глупых проблем iOS:
Теперь ваши текстовые поля имеют расширение
.maxLength
.Вполне нормально установить это значение в раскадровке во время разработки или установить его в коде во время работы приложения.
// simply have this in any Swift file, say, Handy.swift import UIKit private var __maxLengths = [UITextField: Int]() extension UITextField { @IBInspectable var maxLength: Int { get { guard let l = __maxLengths[self] else { return 150 // (global default-limit. or just, Int.max) } return l } set { __maxLengths[self] = newValue addTarget(self, action: #selector(fix), for: .editingChanged) } } func fix(textField: UITextField) { let t = textField.text textField.text = t?.prefix(maxLength) } }
Это так просто.
Сноска - в наши дни, чтобы безопасно обрезать
String
быстро, вы просто.prefix(n)
Еще более простая разовая версия ...
Это исправляет все текстовые поля в вашем проекте.
Если вы просто хотите, чтобы в одном конкретном текстовом поле было просто написано «4», и все ...
class PinCodeEntry: UITextField { override func didMoveToSuperview() { super.didMoveToSuperview() addTarget(self, action: #selector(fixMe), for: .editingChanged) } @objc private func fixMe() { text = text?.prefix(4) } }
Фух! Это все, что нужно сделать.
(Просто BTW, вот подобный очень полезный совет , касающиеся UIText View , https://stackoverflow.com/a/42333832/294884 )
Для программиста ОКР (вроде меня) ...
Как напоминает @LeoDabus,
.prefix
возвращает подстроку. Если вы невероятно заботливы, этоlet t = textField.text textField.text = t?.prefix(maxLength)
было бы
if let t: String = textField.text { textField.text = String(t.prefix(maxLength)) }
Наслаждайтесь!
источник
Swift 4, просто используйте:
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { return range.location < 10 }
источник
string.count < MAX_LENGTH
Так же, как это сделал Стивен Шматц, но с использованием Swift 3.0:
//max Length func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let maxLength = 4 let currentString: NSString = textField.text! as NSString let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString return newString.length <= maxLength }
источник
Для Swift 5:
просто напишите одну строку, чтобы установить максимальную длину символа:
self.textField.maxLength = 10
Больше подробностей нажмите здесь
Кредит: http://www.swiftdevcenter.com/max-character-limit-of-uitextfield-and-allowed-characters-swift/
источник
Думаю, для этого удобнее расширение. Смотрите полный ответ здесь
private var maxLengths = [UITextField: Int]() // 2 extension UITextField { // 3 @IBInspectable var maxLength: Int { get { // 4 guard let length = maxLengths[self] else { return Int.max } return length } set { maxLengths[self] = newValue // 5 addTarget( self, action: #selector(limitLength), forControlEvents: UIControlEvents.EditingChanged ) } } func limitLength(textField: UITextField) { // 6 guard let prospectiveText = textField.text where prospectiveText.characters.count > maxLength else { return } let selection = selectedTextRange // 7 text = prospectiveText.substringWithRange( Range<String.Index>(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength)) ) selectedTextRange = selection } }
источник
Другие решения, опубликованные выше, создают цикл сохранения из-за карты текстового поля. Кроме того,
maxLength
свойство должно допускать значение NULL, если не установлено вместо искусственныхInt.max
конструкций; и цель будет установлена несколько раз, если maxLength изменится.Здесь обновленное решение для Swift4 со слабой картой для предотвращения утечек памяти и другими исправлениями.
private var maxLengths = NSMapTable<UITextField, NSNumber>(keyOptions: NSPointerFunctions.Options.weakMemory, valueOptions: NSPointerFunctions.Options.strongMemory) extension UITextField { var maxLength: Int? { get { return maxLengths.object(forKey: self)?.intValue } set { removeTarget(self, action: #selector(limitLength), for: .editingChanged) if let newValue = newValue { maxLengths.setObject(NSNumber(value: newValue), forKey: self) addTarget(self, action: #selector(limitLength), for: .editingChanged) } else { maxLengths.removeObject(forKey: self) } } } @IBInspectable var maxLengthInspectable: Int { get { return maxLength ?? Int.max } set { maxLength = newValue } } @objc private func limitLength(_ textField: UITextField) { guard let maxLength = maxLength, let prospectiveText = textField.text, prospectiveText.count > maxLength else { return } let selection = selectedTextRange text = String(prospectiveText[..<prospectiveText.index(from: maxLength)]) selectedTextRange = selection } }
источник
Простое решение без использования делегата:
TEXT_FIELD.addTarget(self, action: #selector(editingChanged(sender:)), for: .editingChanged) @objc private func editingChanged(sender: UITextField) { if let text = sender.text, text.count >= MAX_LENGHT { sender.text = String(text.dropLast(text.count - MAX_LENGHT)) return } }
источник
Моя версия Swift 4
shouldChangeCharactersIn
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { guard let preText = textField.text as NSString?, preText.replacingCharacters(in: range, with: string).count <= MAX_TEXT_LENGTH else { return false } return true }
источник
Мне есть что добавить к ответу Аладина:
Ваш контроллер представления должен соответствовать
UITextFieldDelegate
class MyViewController: UIViewController, UITextViewDelegate { }
Задайте делегата вашего текстового поля: чтобы установить делегата, вы можете управлять перетаскиванием из текстового поля в контроллер представления в раскадровке. Я думаю, что это предпочтительнее, чем устанавливать его в коде
Реализуйте метод в вашем контроллере представления:
textField(_:shouldChangeCharactersInRange:replacementString:)
источник
Даю дополнительный ответ на основе @Frouo. Я думаю, что его ответ - самый красивый. Потому что это обычный элемент управления, который мы можем использовать повторно. И здесь нет проблемы с утечкой.
private var kAssociationKeyMaxLength: Int = 0 extension UITextField { @IBInspectable var maxLength: Int { get { if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLength) as? Int { return length } else { return Int.max } } set { objc_setAssociatedObject(self, &kAssociationKeyMaxLength, newValue, .OBJC_ASSOCIATION_RETAIN) self.addTarget(self, action: #selector(checkMaxLength), for: .editingChanged) } } //The method is used to cancel the check when use Chinese Pinyin input method. //Becuase the alphabet also appears in the textfield when inputting, we should cancel the check. func isInputMethod() -> Bool { if let positionRange = self.markedTextRange { if let _ = self.position(from: positionRange.start, offset: 0) { return true } } return false } func checkMaxLength(textField: UITextField) { guard !self.isInputMethod(), let prospectiveText = self.text, prospectiveText.count > maxLength else { return } let selection = selectedTextRange let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength) text = prospectiveText.substring(to: maxCharIndex) selectedTextRange = selection } }
источник
обновление для этого толстого ответа
благодаря
extension UITextField { /// Runtime key private struct AssociatedKeys { /// max lenght key static var maxlength: UInt8 = 0 /// temp string key static var tempString: UInt8 = 0 } /// Limit the maximum input length of the textfiled @IBInspectable var maxLength: Int { get { return objc_getAssociatedObject(self, &AssociatedKeys.maxlength) as? Int ?? 0 } set { objc_setAssociatedObject(self, &AssociatedKeys.maxlength, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) addTarget(self, action: #selector(handleEditingChanged(textField:)), for: .editingChanged) } } /// temp string private var tempString: String? { get { return objc_getAssociatedObject(self, &AssociatedKeys.tempString) as? String } set { objc_setAssociatedObject(self, &AssociatedKeys.tempString, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } /// When the text changes, process the amount of text in the input box so that its length is within the controllable range. @objc private func handleEditingChanged(textField: UITextField) { /// Special Processing for Chinese Input Method guard markedTextRange == nil else { return } if textField.text?.count == maxLength { /// SET lastQualifiedString where text length == max lenght tempString = textField.text } else if textField.text?.count ?? 0 < maxLength { /// clear lastQualifiedString when text lengeht > maxlength tempString = nil } /// keep current text range in arcgives let archivesEditRange: UITextRange? if textField.text?.count ?? 0 > maxLength { /// if text length > maxlength,remove last range,to move to -1 postion. let position = textField.position(from: safeTextPosition(selectedTextRange?.start), offset: -1) ?? textField.endOfDocument archivesEditRange = textField.textRange(from: safeTextPosition(position), to: safeTextPosition(position)) } else { /// just set current select text range archivesEditRange = selectedTextRange } /// main handle string max length textField.text = tempString ?? String((textField.text ?? "").prefix(maxLength)) /// last config edit text range textField.selectedTextRange = archivesEditRange } /// get safe textPosition private func safeTextPosition(_ optionlTextPosition: UITextPosition?) -> UITextPosition { /* beginningOfDocument -> The end of the the text document. */ return optionlTextPosition ?? endOfDocument } }
источник
Работа в Swift4
// ШАГ 1 устанавливает UITextFieldDelegate
class SignUPViewController: UIViewController , UITextFieldDelegate { @IBOutlet weak var userMobileNoTextFiled: UITextField! override func viewDidLoad() { super.viewDidLoad()
// ШАГ 2 установка делегата
userMobileNoTextFiled.delegate = self // установка делегата}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // guard let text = userMobileNoTextFiled.text else { return true } // let newLength = text.count + string.count - range.length // return newLength <= 10 // }
// ШАГ 3 вызывает функцию
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let maxLength = 10 // set your need let currentString: NSString = textField.text! as NSString let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString return newString.length <= maxLength } }
источник
Это ответ для Swift 4, и он довольно прост с возможностью пропускать backspace.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { return textField.text!.count < 10 || string == "" }
источник
Просто проверьте количество символов в строке
class YorsClassName : UITextFieldDelegate { }
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { if textField.text?.count == 1 { return false } return true }
Примечание: здесь я проверил только char, разрешенный в textField
источник
Символ ограничения текстового поля после блока текста в Swift 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,replacementString string: String) -> Bool { if textField == self.txtDescription { let maxLength = 200 let currentString: NSString = textField.text! as NSString let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString return newString.length <= maxLength } return true }
источник
На всякий случай не забывайте охранять размер диапазона перед его применением к строке. В противном случае произойдет сбой, если пользователь сделает следующее:
Введите текст максимальной длины Вставьте что-нибудь (ничего не будет вставлено из-за ограничения длины, но iOS не знает об этом) Отменить вставку (происходит сбой, диапазон причин будет больше фактического размера строки)
Также при использовании iOS 13 пользователи могут случайно вызвать это жестами.
Предлагаю вам добавить в свой проект это
extension String { func replace(with text: String, in range: NSRange) -> String? { guard range.location + range.length <= self.count else { return nil } return (self as NSString).replacingCharacters(in: range, with: text) } }
И используйте это так:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { guard let newText = textView.text.replace(with: text, in: range) else { return false } return newText.count < maxNumberOfCharacters }
В противном случае ваше приложение будет постоянно падать.
источник
Вот альтернатива Swift 3.2+, которая позволяет избежать ненужных манипуляций со строками. В этом случае максимальная длина 10:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let text = textField.text ?? "" return text.count - range.length + string.count <= 10 }
источник
Я использую этот шаг, сначала установите texfield делегата в viewdidload.
override func viewDidLoad() { super.viewDidLoad() textfield.delegate = self }
а затем shouldChangeCharactersIn после включения UITextFieldDelegate.
extension viewController: UITextFieldDelegate { func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let newLength = (textField.text?.utf16.count)! + string.utf16.count - range.length if newLength <= 8 { return true } else { return false } } }
источник
Если у вас есть несколько текстовых полей с проверками разной длины на одной странице, я нашел простое и короткое решение.
class MultipleTextField: UIViewController { let MAX_LENGTH_TEXTFIELD_A = 10 let MAX_LENGTH_TEXTFIELD_B = 11 lazy var textFieldA: UITextField = { let textField = UITextField() textField.tag = MAX_LENGTH_TEXTFIELD_A textField.delegate = self return textField }() lazy var textFieldB: UITextField = { let textField = UITextField() textField.tag = MAX_LENGTH_TEXTFIELD_B textField.delegate = self return textField }() } extension MultipleTextField: UITextFieldDelegate { func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { return (range.location < textField.tag) && (string.count < textField.tag) } }
источник