Question Définir la longueur maximale des caractères d'un objet UITextField


Comment puis-je définir le nombre maximum de caractères dans un UITextField sur le SDK iPhone quand je charge un UIView?


441
2018-01-11 18:08


origine


Réponses:


Tandis que le UITextField la classe n'a pas de propriété de longueur maximale, il est relativement simple d'obtenir cette fonctionnalité en définissant le champ de texte delegate et 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?.characters.count ?? 0
    if (range.length + range.location > currentCharacterCount){
        return false
    }
    let newLength = currentCharacterCount + string.characters.count - range.length
    return newLength <= 25
}

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

Lorsque vous tapez 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 remplaçons / supprimons rien. Insérer au milieu d'un champ de texte signifie simplement un autre range.locationet coller plusieurs caractères signifie simplement string a plus d'un caractère.

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

Une note sur le bogue "défaire"

Comme mentionné dans les commentaires, il y a un bug avec UITextField cela peut conduire à un accident.

Si vous collez dans le champ, mais que votre implémentation de validation empêche le collage, l'opération de collage est toujours enregistrée dans le tampon d'annulation de l'application. Si vous lancez ensuite une annulation (en secouant l’appareil et en confirmant l’annulation), le UITextField va essayer de remplacer la chaîne, il pense il s'est collé à lui-même avec une chaîne vide. Cela va planter parce que jamais réellement collé la chaîne dans lui-même. Il va essayer de remplacer une partie de la chaîne qui n'existe pas.

Heureusement, vous pouvez protéger le UITextField de se tuer comme ça. Il vous suffit de vous assurer que la gamme qu’elle propose de remplacer Est-ce que existe dans sa chaîne actuelle. C'est ce que fait la vérification de la santé mentale initiale ci-dessus.

swift 3.0 avec copier et coller fonctionne correctement.

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 cela vous sera utile.


972
2017-11-20 21:10



Merci août! (Poster)

C'est le code avec lequel 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
2018-01-11 19:40



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 résolu.

enter image description here


32
2018-04-22 16:56



Compléter août réponse, une mise en œuvre possible de la fonction proposée (voir Délégué de UITextField).

Je n'ai pas testé domness code, mais le mien ne reste pas bloqué si l’utilisateur atteint la limite, et il est compatible avec une nouvelle chaîne qui vient remplacer 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
2018-04-16 07:51



Vous ne pouvez pas le faire directement - UITextField n'a pas longueur maximaleattribut, mais vous pouvez définir la UITextField's déléguer, puis utiliser:

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

17
2018-01-11 18:42



Vous avez souvent plusieurs champs de saisie de 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
2017-09-07 07:39



Le meilleur moyen serait de configurer une notification sur le changement de texte. Dans ton -awakeFromNib de votre méthode de contrôleur de vue que vous voulez:

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

Puis, 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 relier la sortie myTextField à ton UITextField et cela ne vous laissera pas ajouter d'autres caractères après avoir atteint la limite. Veillez à ajouter ceci à votre méthode dealloc:

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

12
2018-01-11 19:19



j'ai crée ce Sous-classe UITextFieldLimit:

  • Plusieurs champs de texte pris en charge
  • Définir la limite de longueur du texte
  • La prévention de la pâte
  • Affiche une étiquette de caractères à gauche dans le champ de texte, se cache lorsque vous arrêtez d'éditer.
  • Secouez l'animation quand aucun personnage n'est parti.

Prenez le UITextFieldLimit.h et UITextFieldLimit.m à partir de ce dépôt GitHub:

https://github.com/JonathanGurebo/UITextFieldLimit

et commence à tester!

Marquez votre UITextField créé par le 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 souhaitez 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 du 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 aidera. Bonne chance!


11
2018-04-12 22:37



Cela devrait suffire à résoudre le problème (remplacer 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
2017-08-20 10:10



Je simule le remplacement de la chaîne qui va arriver pour calculer la longueur de la 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
2017-07-28 04:58