web-dev-qa-db-fra.com

Définir la longueur maximale de caractères d'un UITextField

Comment définir le nombre maximal de caractères d'une UITextField sur le kit de développement logiciel (SDK) pour iPhone lorsque je charge une UIView

453
Domness

Alors que la classe UITextField n'a pas de propriété de longueur maximale, il est relativement simple d'obtenir cette fonctionnalité en définissant le delegate du champ de texte et en implémentant la méthode de délégation suivante:

Objectif c

- (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;
}

Rapide

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
}

Avant que le champ de texte ne soit modifié, UITextField demande au délégué si le texte spécifié devrait doit être modifié. Le champ de texte n'ayant pas changé à ce stade, nous saisissons sa longueur actuelle et la longueur de la chaîne que nous insérons (soit en collant du texte copié, soit en tapant un seul caractère à l'aide du clavier), moins la longueur de la plage. Si cette valeur est trop longue (plus de 25 caractères dans cet exemple), renvoyez NO pour interdire la modification.

Lorsque vous saisissez un seul caractère à la fin d'un champ de texte, le range.location sera la longueur du champ actuel et range.length sera 0 car nous ne remplacerons/supprimerons rien. L'insertion au milieu d'un champ de texte signifie simplement un range.location différent, et le collage de plusieurs caractères signifie simplement que string contient plus d'un caractère.

La suppression de caractères uniques ou la suppression de plusieurs caractères est spécifiée par une variable range avec une longueur non nulle et une chaîne vide. Le remplacement est simplement une suppression de plage avec une chaîne non vide.

Une note sur le bogue "annuler" qui se bloque

Comme mentionné dans les commentaires, il y a un bogue avec UITextField qui peut conduire à un crash.

Si vous collez dans le champ, mais que le collage est empêché par votre implémentation de validation, l'opération de collage est toujours enregistrée dans le tampon d'annulation de l'application. Si vous déclenchez ensuite une annulation (en secouant le périphérique et en confirmant l'annulation), le UITextField tentera de remplacer la chaîne qu'il pense qu'il a collée sur elle-même avec une chaîne vide. Cela va planter car il ne collera jamais en fait la chaîne sur elle-même. Il essaiera de remplacer une partie de la chaîne qui n'existe pas.

Heureusement, vous pouvez empêcher le UITextField de se tuer ainsi. Vous devez simplement vous assurer que la plage proposée pour remplacer existe existe dans sa chaîne actuelle. C’est ce que fait le contrôle de cohérence initial ci-dessus.

Swift 3.0 avec copier et coller fonctionne 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
    }

J'espère que ça vous sera utile.

998
sickp

Merci Août! ( Poste )

C'est le code que j'ai fini avec qui fonctionne:

#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;}
}
56
Domness

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

Edit: problème de fuite de mémoire corrigé.

 enter image description here

45
frouo

Pour compléter la réponse August, une implémentation possible de la fonction proposée (voir Délégué de UITextField ).

Je n'ai pas testé le code domness, mais les miens ne sont pas bloqués si l'utilisateur atteint la limite, et il est compatible avec une nouvelle chaîne qui remplace une chaîne plus petite ou égale.

-(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);
}
21
Jmini

Vous ne pouvez pas faire cela directement - UITextField n'a pas d'attribut maxLength , mais vous pouvez définir le délégué UITextField's, puis utiliser:

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

Souvent, vous avez plusieurs champs de saisie avec une longueur différente.

- (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
    }
}
13
Vincent

Le meilleur moyen serait de configurer une notification lorsque le texte est modifié. Dans votre -awakeFromNib de votre méthode de contrôleur de vue, vous voudrez:

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

Ensuite, dans la même classe, ajoutez:

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

Puis reliez la sortie myTextField à votre UITextField et elle ne vous laissera plus ajouter de caractères après avoir atteint la limite. Assurez-vous d’ajouter ceci à votre méthode dealloc:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UITextFieldTextDidChangeNotification" object:myTextField];
12
Martin Pilkington

J'ai créé this UITextFieldLimit subclass:

  • Plusieurs champs de texte pris en charge
  • Définir la limite de longueur du texte
  • Prévention de la pâte
  • Affiche une étiquette des caractères restants à l'intérieur du champ de texte, qui est masqué lorsque vous arrêtez la modification.
  • Secouez l'animation quand il ne reste plus aucun personnage.

Prenez le UITextFieldLimit.h et le UITextFieldLimit.m dans ce dépôt GitHub:

https://github.com/JonathanGurebo/UITextFieldLimit

et commencez à tester!

Marquez votre UITextField créé par un storyboard et liez-le à ma sous-classe à l'aide de l'inspecteur d'identité:

Identity Inspector

Ensuite, vous pouvez le lier à un IBOutlet et définir la limite (la valeur par défaut est 10).


Votre fichier ViewController.h doit contenir: (si vous ne voulez pas modifier le paramètre, comme la limite)

#import "UITextFieldLimit.h"

/.../

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

Votre fichier ViewController.m devrait @synthesize textFieldLimit.


Définissez la limite de longueur de texte dans votre fichier 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.
}

J'espère que la classe vous aide. Bonne chance!

11
Jonathan Gurebo

Cela devrait suffire à résoudre le problème (remplacez 4 par la limite que vous voulez). Assurez-vous simplement d’ajouter un délégué dans IB.

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

Je simule le remplacement de la chaîne qui est sur le point de se produire pour calculer la longueur de cette future chaîne:

- (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;
}
7
samvermette

Swift 3 version//***** Cela ne fonctionnera PAS avec Swift 2.x! ***** //

Commencez par créer un nouveau fichier Swift: TextFieldMaxLength.Swift, .__, puis ajoutez le code ci-dessous:

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

et ensuite, vous verrez dans le Storyboard un nouveau champ (Longueur maximale) lorsque vous sélectionnez un élément TextField.

si vous avez encore des questions, consultez ce lien: http://www.globalnerdy.com/2016/05/18/ios-programming-trick-trick-how-to-use-xcode-to-set-a-text -fields-longueur-maximum-visuel-style-studio/

7
Gilad Brunfman

Le code suivant est similaire à la réponse de sickp mais gère correctement les opérations de copier-coller. Si vous essayez de coller un texte plus long que la limite, le code suivant tronquera le texte pour l'adapter à la limite au lieu de refuser complètement l'opération de coller.

- (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;
    }
}
6
wroluk

En utilisant le constructeur d’interface, vous pouvez créer un lien et obtenir l’événement pour "Modification modifiée" dans n’importe laquelle de vos fonctions . Maintenant, vous pouvez y vérifier la longueur.

- (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;
    }

}
6
Vishal Kumar

Il existe solution générique pour définir la longueur maximale dans Swift . Avec IBInspectable, vous pouvez ajouter un nouvel attribut dans l'inspecteur d'attributs Xcode . enter image description here

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
    }

}
5
Hiren

Pour que cela fonctionne avec couper/coller des chaînes de n'importe quelle longueur, je suggérerais de changer la fonction en quelque chose comme: 

#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;
        }
    }
5
Påhl Melin

Swift 2.0 +

Tout d’abord, créez une classe pour ce processus. Appelons-le StringValidator.Swift.

Ensuite, collez simplement le code suivant à l'intérieur.

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
}

}

Maintenant, sauvez la classe .....

Utilisation ..

Allez maintenant dans votre classe viewController.Swift et faites en sorte que les sorties de votre ..

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

Maintenant, allez à la méthode shouldChangeCharactersInRange du champ de texte et utilisez comme suit.

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
    }

}

N'oubliez pas de définir le protocole délégué/les méthodes des champs de texte.

Laissez-moi expliquer à ce sujet ... J'utilise le processus d'extension simple de chaîne que j'ai écrit dans une autre classe. Maintenant, j'appelle simplement ces méthodes d'extension depuis une autre classe où j'en ai besoin en ajoutant check et une valeur maximale.

Caractéristiques...

  1. Il définira la limite maximale d'un champ de texte particulier.
  2. Il définira le type de clés acceptées pour un champ de texte particulier.

Les types...

containsOnlyCharactersIn // Accepte uniquement les caractères.

containsCharactersIn // Accepte une combinaison de caractères

doesNotContainsCharactersIn // N'acceptera pas les caractères

J'espère que cela a aidé .... Merci ..

3
onCompletion

Swift 3.0

Ce code fonctionne correctement lorsque vous collez une chaîne supérieure aux limites de votre caractère.

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
    }

Merci pour vos votes. :)

3
Ilesh

Utilisez l'extension ci-dessous pour définir la longueur de caractère maximale d'une UITextField et 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
        }
    }

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

Vous pouvez définir la limite ci-dessous.

 enter image description here

2
Hitesh Surani

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
}
2
Shan Ye

Je donne une réponse complémentaire basée sur @Frouo. Je pense que sa réponse est la plus belle façon. Parce que c'est un contrôle commun que nous pouvons réutiliser. 

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
    }

}
2
Victor Choy

Pour Xamarin:

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

C’est la bonne façon de gérer la longueur maximale sur UITextField. Elle permet à la touche de retour de quitter le champ de texte à quitter en tant que premier répondeur et à l'utilisateur de revenir en arrière une fois la limite atteinte.

- (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;
    }
}
2
anders

Si vous voulez limiter le nombre de textes pour vous assurer que le texte tiendra également dans un libellé UILabel, évitez d'utiliser le nombre de caractères. Il tombe en panne avec certains emoji (essayer de tronquer un emoji double taille plantera votre application). C'est également un problème avec certaines langues comme le japonais et le chinois, qui ont un processus de saisie en deux étapes dans lequel un compte simple ne fonctionne tout simplement pas. 

J'ai construit une sous-classe de classe UITextField ( MPC_CharacterLimitedTextField sur github ). Vous lui fournissez la largeur d'étiquette de sortie attendue et il gérera toutes les langues, les problèmes emoji et de collage. Il ne récoltera que le nombre de caractères complets qui s'intégrera dans l'étiquette, quel que soit le nombre de caractères. Il y a une démonstration dans le projet afin que vous puissiez le tester pour voir si c'est ce dont vous avez besoin. J'espère que cela aidera tous ceux qui avaient les mêmes problèmes de longueur de sortie que moi. 

1
Mike Critchley

Je l'ai fait dans Swift pour une limite de 8 caractères avec un pavé numérique.

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

Je devais tester string! = "" Pour permettre au bouton de suppression de fonctionner sur le pavé numérique, sinon il ne permettrait pas de supprimer des caractères dans le champ de texte après son maximum.

1
u84six

maintenant combien de caractères tu veux juste donner des valeurs

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

J'ai implémenté une extension UITextField pour y ajouter une propriété maxLength.

Il est basé sur Xcode 6 IBInspectables, vous pouvez donc définir la limite maxLength sur le générateur Interface.

Voici l'implémentation:

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
1
Lefteris

Je l'ai eu à 1 ligne de code :)

Définissez le délégué de votre vue texte sur "self", puis ajoutez le <UITextViewDelegate> dans votre .h et le code suivant dans votre .m .... vous pouvez ajuster le nombre "7" pour qu'il corresponde à votre nombre MAXIMUM de caractères. 

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

Ce code permet de saisir de nouveaux caractères, de supprimer des caractères, de sélectionner des caractères, puis de les saisir ou de les supprimer, de sélectionner des caractères et de couper, coller en général, de sélectionner des caractères et de coller.

Terminé!






Alternativement, un autre moyen intéressant d’écrire ce code avec des opérations sur bits serait:

-(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));
}
1
Albert Renshaw

D'autres réponses ne gèrent pas le cas où l'utilisateur peut coller une longue chaîne du presse-papiers. Si je colle une longue chaîne, elle devrait simplement être tronquée, mais affichée .

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'

}
1
8suhas

J'ai ouvert la source d'une sous-classe UITextField, STATextField , qui offre cette fonctionnalité (et bien plus encore) avec sa propriété maxCharacterLength.

1
Stunner

Utilisez ce code ici. RESTRICTED_LENGTH est la longueur que vous souhaitez limiter pour textfield.

   - (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;

}
1
Amit Shelgaonkar

Méthode Swift 4.2 et UITextFieldDelegate

Cela fonctionne pour moi et limite le champ de texte à une entrée maximale de 8 caractères. Espérons que NSRange sera éventuellement remplacé par Range, mais pour l’instant, je suis heureux d’utiliser NSString, car la création d’une plage à partir de NSRange implique de traiter avec une autre option.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let text = textField.text ?? ""
    let nsString = text as NSString
    let newText = nsString.replacingCharacters(in: range, with: string)
    return newText.count <= 8
}
1
Edward

Qu'en est-il de cette approche simple. Cela fonctionne bien pour moi.

extension UITextField {

    func  charactersLimit(to:Int) {

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

Ensuite:

someTextField.charactersLimit(to:16)
0
Joaquin Pereira

Swift 4.2 +

En implémentant la méthode UITextFieldDelegate

...
let MAX_LENGTH = 256
...

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    var newText = ""
    // always zero when we add characted
    if range.length == 0 {
        newText = ((textField.text ?? "") + string).count
    } 
    // delete/cut/copy/paste character(s)
    else if var text = textField.text, let sRange = Range<String.Index>.init(range, in: text) {
        text.removeSubrange(sRange)
        text.insert(contentsOf: string, at: text.index(text.startIndex, offsetBy: range.location))
        newText = text
    }
    return newText.count < MAX_LENGTH
}
0
Pocheshire

Je veux ajouter à la réponse donnée par @sickp.

Il y a un problème dans son code Swift qui se produit avec un texte multi-octets (par exemple, emojis). NSRange et String dans Swift ne sont pas compatibles, il est donc frustrant que la classe delegate les combine. L'astuce consiste simplement à convertir les objets String en NSString. La solution correcte, basée sur ce que @sickp a écrit, est en réalité la suivante:

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

    let currentText = (textField.text as NSString?) ?? NSString()
    let currentCharacterCount = currentText.length
    if range.length + range.location > currentCharacterCount {
        return false
    }
    let newLength = currentText.replacingCharacters(in: range, with: string).characters.count
    return newLength <= 25
}
0
Guy Kogus

pour Swift 3.1 ou version ultérieure

tout d'abord ajouter le protocole UITextFieldDelegate 

comme:-

class PinCodeViewController: UIViewController, UITextFieldDelegate { 
.....
.....
.....

}

après cela, créez votre UITextField et définissez le délégué.

Complete Exp: -

import UIKit

class PinCodeViewController: UIViewController, UITextFieldDelegate {

let pinCodetextField: UITextField = {
    let tf = UITextField()
    tf.placeholder = "please enter your pincode"
    tf.font = UIFont.systemFont(ofSize: 15)
    tf.borderStyle = UITextBorderStyle.roundedRect
    tf.autocorrectionType = UITextAutocorrectionType.no
    tf.keyboardType = UIKeyboardType.numberPad
    tf.clearButtonMode = UITextFieldViewMode.whileEditing;
    tf.contentVerticalAlignment = UIControlContentVerticalAlignment.center
 return tf
  }()


 override func viewDidLoad() {
   super.viewDidLoad()
   view.addSubview(pinCodetextField)
    //----- setup your textfield anchor or position where you want to show it----- 


    // after that 
pinCodetextField.delegate = self // setting the delegate

 }
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    return !(textField.text?.characters.count == 6 && string != "")
     } // this is return the maximum characters in textfield 
    }
0
kishu mewara
(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];

    if ([txt_name.text length]>100)
    {
        return NO;
    }

    return YES;
}
0
Mubin Shaikh

Le problème avec certaines des réponses données ci-dessus est, par exemple, j'ai un champ texte et je dois définir une limite de 15 caractères, puis il s'arrête après la saisie du 15ème caractère. mais ils ne permettent pas de supprimer. C'est le bouton supprimer aussi ne fonctionnent pas. Comme je faisais face au même problème. Entré avec la solution, donnée ci-dessous. Fonctionne parfaitement pour moi

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
 if(textField.tag==6)
 {
    if ([textField.text length]<=30)
    {
        return YES;   
    }
    else if([@"" isEqualToString:string])
    {
        textField.text=[textField.text substringToIndex:30 ];
    }

    return NO;
 }
 else
 {
    return YES;
 }
}

J'ai un champ de texte, dont l'étiquette j'ai mis "6" Et j'ai restreint la limite maximum de caractères = 30; Fonctionne bien dans tous les cas 

0
Jasmeet

Cela limite le nombre de caractères, mais veillez également à pouvoir coller dans le champ jusqu'à la limite maximale.

- (void)textViewDidChange:(UITextView *)textView
{
    NSString* str = [textView text];
    str = [str substringToIndex:MIN(1000,[str length])];
    [textView setText:str];

    if([str length]==1000) {
        // show some label that you've reached the limit of 1000 characters
    }
}
0
jacklehamster

Pour Swift 2.1+

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

    if (range.length + range.location > textField.text!.characters.count )
    {
        return false;
    }

    let newLength = textField.text!.characters.count + string.characters.count - range.length
    return newLength <= 25
}

J'espère que ça aide

0
ColossalChris

nous pouvons définir la plage de textfield comme ceci ..

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range  replacementString:(NSString *)string
{
     int setrange = 20;
     return !([textField.text length]>setrange && [string length] > range.length);
}
0
Ricky

Un peu au-delà de la réponse à la question initiale et du développement de la réponse de Frouo, voici des extensions permettant de couper une chaîne d'espaces, d'une longueur maximale, et d'utiliser ces extensions de chaîne pour réduire un champ UITextField à une longueur maximale:

// In String_Extensions.Swift

extension String {

  func trimmedString() -> String {
    var trimmedString = self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
    let components = trimmedString.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).filter { count($0) > 0 }
    return " ".join(components)
  }

  func trimmedStringToMaxLength(maxLength: Int) -> String {
    return trimmedString().substringToIndex(advance(startIndex, min(count(self), maxLength))).trimmedString()
  }

}

// In UITextField_Extensions.Swift

private var maxLengthDictionary = [UITextField : Int]()
private var textFieldMaxLength = 20

extension UITextField {

  @IBInspectable var maxLength: Int {
    get {
      if let maxLength = maxLengthDictionary[self] {
        return maxLength
      } else {
        return textFieldMaxLength
      }
    }
    set {
      maxLengthDictionary[self] = newValue < textFieldMaxLength + 1 ? newValue : textFieldMaxLength
    }
  }

  func trimAndLimitToMaxLength() {
    text = text.trimmedStringToMaxLength(maxLength)
  }

}

let someTextField = UITextField()
let someString = "   This   is   a   string   that   is longer than allowable for a text field.   "
someTextField.text = someString
someTextField.trimAndLimitToMaxLength()
println(someTextField.text) // Prints "This is a string tha"
let anotherTextField = UITextField()
anotherTextField.maxLength = 5
anotherTextField.text = someString
anotherTextField.trimAndLimitToMaxLength()
println(anotherTextField.text) // Prints "This"

trimAndLimitToMaxLength() peut être utilisé dans la fonction textFieldDidEndEditing(_:) de UITextFieldDelegate afin qu'un utilisateur puisse entrer ou coller une chaîne plus longue qu'acceptable, puis la raccourcir au lieu de simplement couper l'entrée à la longueur maximale. Ce faisant, je définirais également les styles de texte attribués pour indiquer toute partie du texte dépassant la longueur acceptable (par exemple, [NSBackgroundColorAttributeName : UIColor.redColor(), NSForegroundColorAttributeName : UIColor.whiteColor(), NSStrikethroughStyleAttributeName : NSNumber(int: 1)]

0
Scott Gardner

Vous pouvez également le faire en utilisant NotificationCenter dans Swift 4  

NotificationCenter.default.addObserver(self, selector: #selector(self.handleTextChange(recognizer:)), name: NSNotification.Name.UITextFieldTextDidChange, object: yourTextField)

    @objc func handleTextChange(recognizer: NSNotification) {
            //max length is 50 charater max
            let textField = recognizer.object as! UITextField

            if((textField.text?.count)! > 50) {
                let newString: String? = (textField.text as NSString?)?.substring(to: 50)
                textField.text = newString

            }         
        }
0
Pramod More