Establecer la longitud máxima de caracteres de un UITextField

Respuestas:

1029

Si bien la UITextFieldclase no tiene una propiedad de longitud máxima, es relativamente simple obtener esta funcionalidad configurando los campos de texto delegatee implementando el siguiente método de delegado:

C objetivo

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    // Prevent crashing undo bug – see note below.
    if(range.length + range.location > textField.text.length)
    {
        return NO;
    }

    NSUInteger newLength = [textField.text length] + [string length] - range.length;
    return newLength <= 25;
}

Rápido

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    let currentCharacterCount = textField.text?.count ?? 0
    if range.length + range.location > currentCharacterCount {
        return false
    }
    let newLength = currentCharacterCount + string.count - range.length
    return newLength <= 25
}

Antes de que cambie el campo de texto, el UITextField le pregunta al delegado si se debe cambiar el texto especificado . El campo de texto no ha cambiado en este punto, por lo que tomamos su longitud actual y la longitud de la cadena que estamos insertando (ya sea pegando texto copiado o escribiendo un solo carácter con el teclado), menos la longitud del rango. Si este valor es demasiado largo (más de 25 caracteres en este ejemplo), regrese NOpara prohibir el cambio.

Al escribir un solo carácter al final de un campo de texto, range.locationserá la longitud del campo actual y range.lengthserá 0 porque no estamos reemplazando / eliminando nada. Insertar en el medio de un campo de texto solo significa un carácter diferente range.location, y pegar varios caracteres solo significa que stringtiene más de un carácter.

La eliminación de caracteres individuales o el corte de varios caracteres se especifica mediante a rangecon una longitud distinta de cero y una cadena vacía. El reemplazo es solo una eliminación de rango con una cadena no vacía.

Una nota sobre el fallo "deshacer"

Como se menciona en los comentarios, hay un error UITextFieldque puede provocar un bloqueo.

Si pega en el campo, pero su implementación de validación previene el pegado, la operación de pegar aún se registra en el búfer de deshacer de la aplicación. Si luego dispara un deshacer (sacudiendo el dispositivo y confirmando un Deshacer), UITextFieldintentará reemplazar la cadena que cree que se pegó en sí misma con una cadena vacía. Esto se bloqueará porque nunca realmente pegar la cadena en sí misma. Intentará reemplazar una parte de la cadena que no existe.

Afortunadamente puedes protegerlo UITextFieldde suicidarse así. Sólo tiene que asegurarse de que el rango se propone sustituir hace existir dentro de su cadena actual. Esto es lo que hace la comprobación de cordura inicial anterior.

Swift 3.0 con copiar y pegar funcionando bien.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let str = (textView.text + text)
        if str.characters.count <= 10 {
            return true
        }
        textView.text = str.substring(to: str.index(str.startIndex, offsetBy: 10))
        return false
    }

Espero que te sea útil.

sickp
fuente
77
Encontró una solución rodeando esas 2 líneas con if (textField == _ssn) {} y agregando return YES; al final del método, que permitirá que todos los demás UITextFields acepten texto sin ninguna restricción. ¡Hábil!
Kyle Clegg
55
Buena respuesta, pero el operador ternario es superfluo; podrías simplemente ponerreturn newLength <= 25;
jowie
2
¿Qué sucede si solo desea que el texto no se derrame sobre el marco del campo de texto; No todos los caracteres tienen el mismo ancho, ¿verdad?
Morkrom
2
Realmente hay un error de deshacer como menciona @bcherry, probado con UITextFieldiPad iOS 8.1. (+1 para comentar). ¿El autor agregaría algo sobre esto, ya que es la respuesta mejor calificada? Estoy feliz de hacer una edición, ¡pero la mía parece ser rechazada regularmente! :-)
Benjohn
8
@bherry En Swift, la comprobación del caso de deshacer parece romper la entrada de emoji. ¿No debería ser el recuento (textField.text) realmente recuento (textField.text.utf16) para que coincida con el informe objc / uikit en rango (frente a la variante de recuento de Swift en cadenas)?
rcw3
62

Swift 4

import UIKit

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)
            addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
        }
    }

    @objc func checkMaxLength(textField: UITextField) {
        guard let prospectiveText = self.text,
            prospectiveText.count > maxLength
            else {
                return
        }

        let selection = selectedTextRange

        let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
        let substring = prospectiveText[..<indexEndOfText]
        text = String(substring)

        selectedTextRange = selection
    }
}

Editar: problema de pérdida de memoria solucionado.

ingrese la descripción de la imagen aquí

frouo
fuente
¡Gran idea Frouo! Lo amplié en mi respuesta para mover el recorte maxLength a una extensión de cadena para que también se pueda usar para cosas como instancias de UITextView y para agregar una función conveniente para aprovechar estas extensiones de cadena en una extensión de UITextField.
Scott Gardner
1
No esta variable global crear pérdidas de memoria, mediante la celebración de las referencias a todos los textviews (que hacen referencia a los superviews hasta Raíz)
Ixx
3
@Ixx He editado para solucionar el problema de pérdida de memoria que señaló + swift 3. Gracias
frouo
1
¡La forma más bella de lograrlo! Gracias
Victor Choy
¿Alguien puede proporcionarme su versión objetiva
MRizwan33
56

Gracias agosto! ( Publicar )

Este es el código con el que terminé que funciona:

#define MAX_LENGTH 20

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (textField.text.length >= MAX_LENGTH && range.length == 0)
    {
        return NO; // return NO to not change text
    }
    else
    {return YES;}
}
Domness
fuente
19
Desafortunadamente, esta solución no puede evitar que los usuarios copien y peguen en un campo de texto, lo que les permite evitar el límite. La respuesta de Sickpea hace frente a esta situación correctamente.
Ant
55
¿Qué pasa con las personas que tienen una declaración if para devolver NO o SÍ? Pruebe esto: return! (TextField.text.length> = MAX_LENGTH && range.length == 0);
Matt Parkins
o estoreturn textField.text.length < MAX_LENGTH || range.length != 0;
igrek
22

Para completar la respuesta de agosto , una posible implementación de la función propuesta (ver delegado de UITextField ).

No probé el código domness , pero el mío no se atasca si el usuario alcanzó el límite, y es compatible con una nueva cadena que viene a reemplazar una más pequeña o igual.

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    //limit the size :
    int limit = 20;
    return !([textField.text length]>limit && [string length] > range.length);
}
Jmini
fuente
17

No puede hacer esto directamente: UITextFieldno tiene el atributo maxLength , pero puede configurar el UITextField'sdelegado y luego usar:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
agosto
fuente
55
Estoy de acuerdo, este es el mejor camino a seguir, pero sigue siendo un poco hack. Envíe un informe de error a Apple que le gustaría ver una propiedad para la longitud del texto. Definitivamente estoy interesado en esto también.
avocade
55
@avocade, no es un truco: es un ejemplo en el que tienes que hacer un código marco básico que Apple debería haber hecho por ti. Hay MUCHOS ejemplos de esto en el SDK de iOS.
Dan Rosenstark
13

A menudo tiene múltiples campos de entrada con una longitud diferente.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    int allowedLength;
    switch(textField.tag) {
        case 1: 
            allowedLength = MAXLENGTHNAME;      // triggered for input fields with tag = 1
            break;
        case 2:
            allowedLength = MAXLENGTHADDRESS;   // triggered for input fields with tag = 2
            break;
        default:
            allowedLength = MAXLENGTHDEFAULT;   // length default when no tag (=0) value =255
            break;
    }

    if (textField.text.length >= allowedLength && range.length == 0) {
        return NO; // Change not allowed
    } else {
        return YES; // Change allowed
    }
}
Vincent
fuente
12

La mejor manera sería configurar una notificación sobre el cambio de texto. En su -awakeFromNibmétodo de controlador de vista, querrá:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(limitTextField:) name:@"UITextFieldTextDidChangeNotification" object:myTextField];

Luego, en la misma clase, agregue:

- (void)limitTextField:(NSNotification *)note {
    int limit = 20;
    if ([[myTextField stringValue] length] > limit) {
        [myTextField setStringValue:[[myTextField stringValue] substringToIndex:limit]];
    }
}

Luego, conecte la salida myTextFielda su UITextFieldy no le permitirá agregar más caracteres después de alcanzar el límite. Asegúrese de agregar esto a su método dealloc:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UITextFieldTextDidChangeNotification" object:myTextField];
Martin Pilkington
fuente
Aunque hice esto para eliminar errores> myTextField.text = [myTextField.text substringToIndex: limit];
Lucas
11

He creado esta subclase UITextFieldLimit:

  • Múltiples campos de texto compatibles
  • Establecer el límite de longitud del texto
  • Prevención de pasta
  • Muestra una etiqueta de los caracteres de la izquierda dentro del campo de texto, se oculta cuando deja de editar.
  • Agite la animación cuando no queden caracteres.

Tome el UITextFieldLimit.hy UITextFieldLimit.mde este repositorio de GitHub:

https://github.com/JonathanGurebo/UITextFieldLimit

y comienza a probar!

Marque su UITextField creado por el guión gráfico y vincúlelo a mi subclase utilizando el Inspector de identidad:

Inspector de identidad

Luego puede vincularlo a un IBOutlet y establecer el límite (el valor predeterminado es 10).


Su archivo ViewController.h debe contener: (si no desea modificar la configuración, como el límite)

#import "UITextFieldLimit.h"

/.../

@property (weak, nonatomic) IBOutlet UITextFieldLimit *textFieldLimit; // <--Your IBOutlet

Su archivo ViewController.m debería @synthesize textFieldLimit.


Establezca el límite de longitud de texto en su archivo ViewController.m:

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

    [textFieldLimit setLimit:25];// <-- and you won't be able to put more than 25 characters in the TextField.
}

Espero que la clase te ayude. ¡Buena suerte!

Jonathan Gurebo
fuente
Por la pequeña necesidad del límite de caracteres, creo que agregar tu clase sería exagerado.
Domness
Aún esfuerzo apreciado.
Reaper
11

Esto debería ser suficiente para resolver el problema (reemplace 4 por el límite que desea). Solo asegúrese de agregar delegado en IB.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
     NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
     return (newString.length<=4);
}
Nishant
fuente
9

Use la extensión a continuación para establecer la longitud máxima de caracteres de a UITextFieldy UITextView.

Swift 4.0

    private var kAssociationKeyMaxLength: Int = 0
    private var kAssociationKeyMaxLengthTextView: 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)
                addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
            }
        }

        @objc func checkMaxLength(textField: UITextField) {
            guard let prospectiveText = self.text,
                prospectiveText.count > maxLength
                else {
                    return
            }

            let selection = selectedTextRange

            let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
            let substring = prospectiveText[..<indexEndOfText]
            text = String(substring)

            selectedTextRange = selection
        }
    }

UITextView

extension UITextView:UITextViewDelegate {


        @IBInspectable var maxLength: Int {
            get {
                if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLengthTextView) as? Int {
                    return length
                } else {
                    return Int.max
                }
            }
            set {
                self.delegate = self

                objc_setAssociatedObject(self, &kAssociationKeyMaxLengthTextView, newValue, .OBJC_ASSOCIATION_RETAIN)
            }
        }

        public func textViewDidChange(_ textView: UITextView) {
            checkMaxLength(textField: self)
        }
        @objc func checkMaxLength(textField: UITextView) {
            guard let prospectiveText = self.text,
                prospectiveText.count > maxLength
                else {
                    return
            }

            let selection = selectedTextRange

            let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
            let substring = prospectiveText[..<indexEndOfText]
            text = String(substring)

            selectedTextRange = selection
        }
    }

Puede establecer el límite a continuación.

ingrese la descripción de la imagen aquí

COVID-19
fuente
La mejor respuesta es, con mucho, una gran solución cuando hay muchos campos de texto que necesitan diferentes longitudes
Carlos Norena
Solución realmente excelente para el campo de texto y el límite de entrada de caracteres de control de vista de texto. También guarda líneas de código y tiempo para el desarrollador ... :)
Sandip Patel - SM
Esto funciona mejor que las otras soluciones que encontré. Por ejemplo, si tiene emojis en su campo de texto, otras extensiones que encontré saltarían al final de la línea al editar. Pero tu código no hace eso. ¡Gracias!
Phontaine Judd
7

Simulo el reemplazo de cadena real que está por suceder para calcular la longitud de esa cadena futura:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];

    if([newString length] > maxLength)
       return NO;

    return YES;
}
samvermette
fuente
7

Versión Swift 3 // ***** ¡Esto NO funcionará con Swift 2.x! ***** //

Primero cree un nuevo archivo Swift: TextFieldMaxLength.swift, y luego agregue el siguiente código:

import UIKit

private var maxLengths = [UITextField: Int]()

extension UITextField {

   @IBInspectable var maxLength: Int {

      get {

          guard let length = maxLengths[self] 
             else {
                return Int.max
      }
      return length
   }
   set {
      maxLengths[self] = newValue
      addTarget(
         self,
         action: #selector(limitLength),
         for: UIControlEvents.editingChanged
      )
   }
}
func limitLength(textField: UITextField) {
    guard let prospectiveText = textField.text,
        prospectiveText.characters.count > maxLength
    else {
        return
    }

   let selection = selectedTextRange
   let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
   text = prospectiveText.substring(to: maxCharIndex)
   selectedTextRange = selection
   }
}

y luego verá en Storyboard un nuevo campo (Longitud máxima) cuando seleccione cualquier TextField

Si aún tiene más preguntas, consulte este enlace: http://www.globalnerdy.com/2016/05/18/ios-programming-trick-how-to-use-xcode-to-set-a-text-fields -maximum-length-visual-studio-style /

Gilad Brunfman
fuente
Advertencia, esta variable global crea pérdidas de memoria, al contener referencias a todas las vistas de texto.
frouo
6

Con el creador de interfaces, puede vincular y obtener el evento "Edición modificada" en cualquiera de sus funciones. Ahora puedes poner cheque por la longitud

- (IBAction)onValueChange:(id)sender 
{
    NSString *text = nil;
    int MAX_LENGTH = 20;
    switch ([sender tag] ) 
    {
        case 1: 
        {
            text = myEditField.text;
            if (MAX_LENGTH < [text length]) {
                myEditField.text = [text substringToIndex:MAX_LENGTH];
            }
        }
            break;
        default:
            break;
    }

}
Vishal Kumar
fuente
6

El siguiente código es similar a la respuesta de sickp pero maneja correctamente las operaciones de copiar y pegar. Si intenta pegar un texto que es más largo que el límite, el siguiente código truncará el texto para que se ajuste al límite en lugar de rechazar la operación de pegar por completo.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    static const NSUInteger limit = 70; // we limit to 70 characters
    NSUInteger allowedLength = limit - [textField.text length] + range.length;
    if (string.length > allowedLength) {
        if (string.length > 1) {
            // get at least the part of the new string that fits
            NSString *limitedString = [string substringToIndex:allowedLength];
            NSMutableString *newString = [textField.text mutableCopy];
            [newString replaceCharactersInRange:range withString:limitedString];
            textField.text = newString;
        }
        return NO;
    } else {
        return YES;
    }
}
wroluk
fuente
6

Hay una solución genérica para configurar la longitud máxima en Swift. Mediante IBInspectable, puede agregar un nuevo atributo en Xcode Attribute Inspector.ingrese la descripción de la imagen aquí

import UIKit
private var maxLengths = [UITextField: Int]()
extension UITextField {

    @IBInspectable var maxLength: Int {
        get {
            guard let length = maxLengths[self]
            else {
                return Int.max
            }
            return length
        }
        set {
            maxLengths[self] = newValue
            addTarget(
                self,
                action: Selector("limitLength:"),
                forControlEvents: UIControlEvents.EditingChanged
            )
        }
    }

    func limitLength(textField: UITextField) {
        guard let prospectiveText = textField.text
            where prospectiveText.characters.count > maxLength else {
                return
        }
        let selection = selectedTextRange
        text = prospectiveText.substringWithRange(
            Range<String.Index>(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength))
        )
        selectedTextRange = selection
    }

}
Hiren
fuente
Solución limpia y perfecta
Eduardo
Mantener un UITextField en un campo global los retendrá en la memoria incluso después de que se descarte el UIViewController. Esta es una pérdida de memoria. No uses este método.
Gunhan
5

Para que funcione con cortar y pegar cadenas de cualquier longitud, sugeriría cambiar la función a algo como:

#define MAX_LENGTH 20

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    {
        NSInteger insertDelta = string.length - range.length;

        if (textField.text.length + insertDelta > MAX_LENGTH)
        {
           return NO; // the new string would be longer than MAX_LENGTH
        }
        else {
            return YES;
        }
    }
Påhl Melin
fuente
4

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
}
Shan Ye
fuente
¿Por qué el guard?
oddRaven
compruebe si el texto es nulo, si lo desea, también puede usar if @oddRaven
Shan Ye
3

Swift 2.0 +

En primer lugar, cree una clase para este proceso. Vamos a llamarlo StringValidator.swift.

Luego solo pegue el siguiente código dentro de él.

import Foundation

extension String {

func containsCharactersIn(matchCharacters: String) -> Bool {
let characterSet = NSCharacterSet(charactersInString: matchCharacters)
return self.rangeOfCharacterFromSet(characterSet) != nil
}

func containsOnlyCharactersIn(matchCharacters: String) -> Bool {
let disallowedCharacterSet = NSCharacterSet(charactersInString: matchCharacters).invertedSet
return self.rangeOfCharacterFromSet(disallowedCharacterSet) == nil
}


func doesNotContainCharactersIn(matchCharacters: String) -> Bool {
let characterSet = NSCharacterSet(charactersInString: matchCharacters)
return self.rangeOfCharacterFromSet(characterSet) == nil
}

func isNumeric() -> Bool
{
let scanner = NSScanner(string: self)
scanner.locale = NSLocale.currentLocale()

return scanner.scanDecimal(nil) && scanner.atEnd
}

}

Ahora guarda la clase .....

Uso..

Ahora vaya a su clase viewController.swift y haga las salidas de su campo de texto como ...

@IBOutlet weak var contactEntryTxtFld: UITextField! //First textfield
@IBOutlet weak var contactEntryTxtFld2: UITextField!   //Second textfield

Ahora vaya al método shouldChangeCharactersInRange del campo de texto y úselo de la siguiente manera.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if string.characters.count == 0 {
        return true
    }
    let latestText = textField.text ?? ""
    let checkAbleText = (latestText as NSString).stringByReplacingCharactersInRange(range, withString: string)


    switch textField {

    case contactEntryTxtFld:
        return checkAbleText.containsOnlyCharactersIn("0123456789") && prospectiveText.characters.count <= 5

    case contactEntryTxtFld2:
        return checkAbleText.containsOnlyCharactersIn("0123456789") && prospectiveText.characters.count <= 5

    default:
        return true
    }

}

No olvide establecer el protocolo delegado / métodos de campos de texto.

Permítanme explicar acerca de esto ... Estoy usando el proceso de extensión simple de cadena que escribí dentro de otra clase. Ahora solo estoy llamando a esos métodos de extensión desde otra clase donde los necesito agregando verificación y valor máximo.

Caracteristicas...

  1. Establecerá el límite máximo de un campo de texto particular.
  2. Establecerá el tipo de claves aceptadas para un campo de texto particular.

Tipos ...

usesOnlyCharactersIn // Acepta solo caracteres.

usesCharactersIn // Acepta la combinación de caracteres

doesNotContainsCharactersIn // No aceptará caracteres

Espero que esto haya ayudado ... Gracias ...

en la terminación
fuente
3

swift 3.0

Este código funciona bien cuando pega una cadena más allá de los límites de su carácter.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let str = (textView.text + text)
        if str.characters.count <= 10 {
            return true
        }
        textView.text = str.substring(to: str.index(str.startIndex, offsetBy: 10))
        return false
    }

Gracias por vuestros votos. :)

Ilesh P
fuente
2
UITextField, no UITextView.
Jonny
3

Doy una respuesta complementaria basada en @Frouo. Creo que su respuesta es la forma más bella. Porque es un control común que podemos reutilizar.

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)
        }
    }

    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
    }

    //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
    }

}
Victor Choy
fuente
2

Esta es la forma correcta de manejar la longitud máxima en UITextField, permite que la tecla de retorno salga del campo de texto para renunciar como primer respondedor y permite que el usuario retroceda cuando alcance el límite

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
int MAX_LENGHT = 5;
    if([string isEqualToString:@"\n"])
    {
        [textField resignFirstResponder];
        return FALSE;
    }
    else if(textField.text.length > MAX_LENGHT-1)
    {
        if([string isEqualToString:@""] && range.length == 1)
        {
            return TRUE;
        }
        else
        {
            return FALSE;
        }
    }
    else
    {
        return TRUE;
    }
}
Anders
fuente
2

¿Qué pasa con este enfoque simple? esta trabajando bien para mi.

extension UITextField {

    func  charactersLimit(to:Int) {

        if (self.text!.count > to) {
            self.deleteBackward()
        }
    }
}

Entonces:

someTextField.charactersLimit(to:16)
Joaquin Pereira
fuente
1

Otras respuestas no manejan el caso en el que el usuario puede pegar una cadena larga desde el portapapeles. Si pego una cadena larga, debería truncarse pero mostrarse. Use esto en su delegado:

static const NSUInteger maxNoOfCharacters = 5;

-(IBAction)textdidChange:(UITextField * )textField
{
NSString * text = textField.text;

if(text.length > maxNoOfCharacters)
{
    text = [text substringWithRange:NSMakeRange(0, maxNoOfCharacters)];
    textField.text = text;
}

// use 'text'

}
8suhas
fuente
1

Lo bajé a 1 línea de código :)

Establezca el delegado de su vista de texto en "self" y luego agregue el <UITextViewDelegate>.h y el siguiente código en su .m ... puede ajustar el número "7" para que sea lo que quiera que sea su número MÁXIMO de caracteres.

-(BOOL)textView:(UITextView *)a shouldChangeTextInRange:(NSRange)b replacementText:(NSString *)c {
    return ((a.text.length+c.length<=7)+(c.length<1)+(b.length>=c.length)>0);
}

Este código explica escribir nuevos caracteres, eliminar caracteres, seleccionar caracteres y luego escribir o eliminar, seleccionar caracteres y cortar, pegar en general y seleccionar caracteres y pegar.

¡Hecho!






Alternativamente, otra forma genial de escribir este código con operaciones de bits sería

-(BOOL)textView:(UITextView *)a shouldChangeTextInRange:(NSRange)b replacementText:(NSString *)c {
    return 0^((a.text.length+c.length<=7)+(c.length<1)+(b.length>=c.length));
}
Albert Renshaw
fuente
1

He abierto una subclase de UITextField, STATextField , que ofrece esta funcionalidad (y mucho más) con su maxCharacterLengthpropiedad.

Persona maravillosa
fuente
1

ahora cuántos caracteres quieres solo da valores

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range   replacementString:(NSString *)string {
     NSUInteger newLength = [textField.text length] + [string length] - range.length;
     return (newLength > 25) ? NO : YES;
  }
mahesh chowdary
fuente
1

Use este código aquí RESTRICTED_LENGTH es la longitud que desea restringir para el campo de texto.

   - (BOOL)textField:(UITextField *)textField     shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (textField == nameTF) {
    int limit = RESTRICTED_LENGTH - 1;
    return !([textField.text length]>limit && [string length] > range.length);
    }
   else
   {
    return YES;
   }

return NO;

}
Amit Shelgaonkar
fuente
1

Hice esto en Swift para un límite de 8 caracteres al usar un teclado numérico.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    return !(textField.text?.characters.count == MAX_LENGTH && string != "")
}

Tuve que probar la cadena! = "" Para permitir que el botón Eliminar funcionara en el teclado numérico, de lo contrario no permitiría eliminar caracteres en el campo de texto después de alcanzar su máximo.

u84six
fuente
1

Para Xamarin:

YourTextField.ShouldChangeCharacters = 
delegate(UITextField textField, NSRange range, string replacementString)
        {
            return (range.Location + replacementString.Length) <= 4; // MaxLength == 4
        };
Kedu
fuente
1

He implementado una extensión UITextField para agregarle una propiedad maxLength.

Se basa en Xcode 6 IBInspectables, por lo que puede establecer el límite maxLength en el generador de interfaces.

Aquí está la implementación:

UITextField + MaxLength.h

#import <UIKit/UIKit.h>

@interface UITextField_MaxLength : UITextField<UITextFieldDelegate>

@property (nonatomic)IBInspectable int textMaxLength;
@end

UITextField + MaxLength.m

#import "UITextField+MaxLength.h"

@interface UITextField_MaxLength()

@property (nonatomic, assign) id <UITextFieldDelegate> superDelegate;

@end

@implementation UITextField_MaxLength

- (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

    //validate the length, only if it's set to a non zero value
    if (self.textMaxLength>0) {
        if(range.length + range.location > textField.text.length)
            return NO;

        if (textField.text.length+string.length - range.length>self.textMaxLength) {
            return NO;
        }
    }

    //if length validation was passed, query the super class to see if the delegate method is implemented there
    if (self.superDelegate && [self.superDelegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) {
        return [self.superDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string];
    }
    else{
        //if the super class does not implement the delegate method, simply return YES as the length validation was passed
        return YES;
    }
}

- (void)setDelegate:(id<UITextFieldDelegate>)delegate {
    if (delegate == self)
        return;
    self.superDelegate = delegate;
    [super setDelegate:self];
}

//forward all non overriden delegate methods
- (id)forwardingTargetForSelector:(SEL)aSelector {
    if ([self.superDelegate  respondsToSelector:aSelector])
        return self.superDelegate;

    return [super forwardingTargetForSelector:aSelector];
}

- (BOOL)respondsToSelector:(SEL)aSelector {
    if ([self.superDelegate respondsToSelector:aSelector])
        return YES;

    return [super respondsToSelector:aSelector];
}
@end
Lefteris
fuente