Sé que hay otros temas sobre esto, pero parece que no puedo averiguar cómo implementarlo.
Estoy tratando de limitar un UITextField a solo 5 caracteres
Preferiblemente alfanumérico y - y. y _
He visto este código
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
}
y
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
}
Simplemente no sé cómo implementarlo o qué "campo de texto" debería cambiar por mi personalizado llamado UITextField
String
en Swift en estos días, finalmente puede simplemente .prefix (n)Respuestas:
Su controlador de vista debe cumplir
UITextFieldDelegate
, como se muestra a continuación:class MyViewController: UIViewController, UITextFieldDelegate { }
Configure el delegado de su campo de texto:
myTextField.delegate = self
Implemente el método en su controlador de vista:
textField(_:shouldChangeCharactersInRange:replacementString:)
Todos juntos:
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 }
Para 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 }
Permitir que solo se ingrese un conjunto específico de caracteres en un campo de texto dado
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 }
Cómo programar un campo de texto de iOS que solo toma entrada numérica con una longitud máxima
fuente
textField
en el métodofunc textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
shouldChangeCharactersInRange
se llama a la devolución de llamada, esto es para todos los campos de texto, recibe la devolución de llamada en el mismo lugarshouldChangeCharactersInRange
y dentro de este método puede saber qué campo de texto se está editando gracias al parámetro pasadotextField
, por ejemplo, puede dar un etiqueta para cada campo de texto y prueba dentro deshouldChangeCharactersInRange
y para cada campo de texto realiza la validación del contenidoDiciembre de 2017. Swift 4.
Tenga cuidado de que gran parte del código de ejemplo que verá en línea con respecto a este problema esté muy desactualizado .
Pegue lo siguiente en cualquier archivo Swift de su proyecto. Puedes nombrar el archivo como quieras, por ejemplo, "Handy.swift".
Esto finalmente soluciona uno de los problemas más estúpidos en iOS:
Sus campos de texto ahora tienen un
.maxLength
.Está completamente bien establecer ese valor en el guión gráfico durante el desarrollo, o configurarlo en código mientras la aplicación se está ejecutando.
// 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) } }
Es así de simple.
Nota al pie: en estos días, para truncar de forma segura un
String
in swift, simplemente.prefix(n)
Una versión única aún más simple ...
Lo anterior corrige todos los campos de texto en su proyecto.
Si solo desea que un campo de texto en particular se limite a decir "4", y eso es todo ...
class PinCodeEntry: UITextField { override func didMoveToSuperview() { super.didMoveToSuperview() addTarget(self, action: #selector(fixMe), for: .editingChanged) } @objc private func fixMe() { text = text?.prefix(4) } }
¡Uf! Eso es todo al respecto.
(Solo por cierto, aquí hay un consejo muy útil similar relacionado con UIText View , https://stackoverflow.com/a/42333832/294884 )
Para el programador de TOC (como yo) ...
Como recuerda @LeoDabus, .prefix devuelve una subcadena. Si eres increíblemente cariñoso, esto
let t = textField.text textField.text = t?.prefix(maxLength)
sería
if let t: String = textField.text { textField.text = String(t.prefix(maxLength)) }
¡Disfrutar!
fuente
Swift 4, simplemente usa:
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { return range.location < 10 }
fuente
string.count < MAX_LENGTH
De la misma manera que lo hizo Steven Schmatz pero usando 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 }
fuente
Para Swift 5:
simplemente escriba una línea para establecer la longitud máxima de caracteres:
self.textField.maxLength = 10
Para más detalles haga clic aquí
Crédito: http://www.swiftdevcenter.com/max-character-limit-of-uitextfield-and-allowed-characters-swift/
fuente
Creo que la extensión es más útil para esto. Vea la respuesta completa aquí
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 } }
fuente
Otras soluciones publicadas anteriormente producen un ciclo de retención debido al mapa de campo de texto. Además, la
maxLength
propiedad debe ser anulable si no se establece en lugar deInt.max
construcciones artificiales ; y el objetivo se establecerá varias veces si se cambia maxLength.Aquí una solución actualizada para Swift4 con un mapa débil para evitar fugas de memoria y otras correcciones
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 } }
fuente
Solución simple sin usar delegado:
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 } }
fuente
Mi versión Swift 4 de
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 }
fuente
Tengo algo que agregar a la respuesta de Aladin:
Su controlador de vista debe cumplir con
UITextFieldDelegate
class MyViewController: UIViewController, UITextViewDelegate { }
Configure el delegado de su campo de texto: para configurar el delegado, puede controlar el arrastre desde el campo de texto a su controlador de vista en el guión gráfico. Creo que esto es preferible a configurarlo en código.
Implemente el método en su controlador de vista:
textField(_:shouldChangeCharactersInRange:replacementString:)
fuente
Doy una respuesta complementaria basada en @Frouo. Creo que su respuesta es la forma más hermosa. Porque es un control común que podemos reutilizar. Y aquí no hay problema de fugas.
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 } }
fuente
actualización para esta respuesta Fattie
Gracias
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 } }
fuente
Trabajando en Swift4
// PASO 1 establece UITextFieldDelegate
class SignUPViewController: UIViewController , UITextFieldDelegate { @IBOutlet weak var userMobileNoTextFiled: UITextField! override func viewDidLoad() { super.viewDidLoad()
// PASO 2 establecer delegado
userMobileNoTextFiled.delegate = self // establecer delegado}
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 // }
// PASO 3 llamar a func
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 } }
fuente
Esta respuesta es para Swift 4, y es bastante sencilla con la capacidad de dejar pasar el retroceso.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { return textField.text!.count < 10 || string == "" }
fuente
Simplemente verifique con el número de caracteres en la cadena
class YorsClassName : UITextFieldDelegate { }
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { if textField.text?.count == 1 { return false } return true }
Nota: Aquí verifiqué solo los caracteres permitidos en textField
fuente
Carácter de límite de TextField después de bloquear el texto en 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 }
fuente
Por si acaso, no olvide proteger el tamaño del rango antes de aplicarlo a la cuerda. De lo contrario, se bloqueará si el usuario hace esto:
Escriba el texto de longitud máxima Inserte algo (No se insertará nada debido a la limitación de longitud, pero iOS no lo sabe) Deshacer la inserción (Se bloquea, porque el rango será mayor que el tamaño real de la cadena)
Además, los usuarios de iOS 13 pueden activar esto accidentalmente mediante gestos
Le sugiero que agregue a su proyecto esto
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) } }
Y utilícelo así:
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 }
De lo contrario, constantemente se bloqueará su aplicación
fuente
Aquí hay una alternativa de Swift 3.2+ que evita la manipulación innecesaria de cadenas. En este caso, la longitud máxima es 10:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let text = textField.text ?? "" return text.count - range.length + string.count <= 10 }
fuente
Utilizo este paso, primero establezca el campo de texto delegado en viewdidload.
override func viewDidLoad() { super.viewDidLoad() textfield.delegate = self }
y luego shouldChangeCharactersIn después de incluir 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 } } }
fuente
Si tiene varios campos de texto que tienen varias verificaciones de longitud en una página, he encontrado una solución fácil y breve.
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) } }
fuente