Domanda

Come posso impostare il numero massimo di caratteri in un UITextField su iPhone SDK quando carico un UIView?

È stato utile?

Soluzione

Sebbene la classe UITextField non abbia proprietà di lunghezza massima, è relativamente semplice ottenere questa funzionalità impostando il campo di testo delegate e implementando il seguente metodo delegato:

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

Swift

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
}

Prima che il campo di testo cambi, UITextField chiede al delegato se il testo specificato dovrebbe essere modificato. A questo punto il campo di testo non è cambiato, quindi prendiamo la lunghezza corrente e la lunghezza della stringa che stiamo inserendo (incollando il testo copiato o digitando un singolo carattere usando la tastiera), meno la lunghezza dell'intervallo. Se questo valore è troppo lungo (più di 25 caratteri in questo esempio), restituire NO per vietare la modifica.

Quando si digita un singolo carattere alla fine di un campo di testo, range.location sarà la lunghezza del campo corrente e range.length sarà 0 perché non stiamo sostituendo / eliminando nulla. Inserire nel mezzo di un campo di testo significa solo un string diverso e incollare più caratteri significa solo che range contiene più di un carattere.

L'eliminazione di singoli caratteri o il taglio di più caratteri è specificato da <=> con una lunghezza diversa da zero e una stringa vuota. La sostituzione è solo una cancellazione dell'intervallo con una stringa non vuota.

Una nota sul " in crash; annulla " bug

Come menzionato nei commenti, c'è un bug con <=> che può portare a un arresto anomalo.

Se si incolla nel campo, ma la copia viene impedita dall'implementazione della convalida, l'operazione incolla viene comunque registrata nel buffer di annullamento dell'applicazione. Se quindi esegui un annullamento (scuotendo il dispositivo e confermando un Annulla), <=> tenterà di sostituire la stringa che pensa incollata su se stessa con una stringa vuota. Questo andrà in crash perché non ha mai effettivamente incollato la stringa su se stesso. Tenterà di sostituire una parte della stringa che non esiste.

Fortunatamente puoi proteggere <=> dall'uccisione in questo modo. Devi solo assicurarti che l'intervallo che propone di sostituire esiste esista all'interno della sua stringa corrente. Questo è ciò che fa il controllo di integrità iniziale sopra.

swift 3.0 con copia e incolla funzionanti.

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
    }

Spero che ti sia utile.

Altri suggerimenti

Grazie agosto! ( Post )

Questo è il codice con cui ho finito che funziona:

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

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

Modifica: problema di perdita di memoria risolto.

 inserisci qui la descrizione dell'immagine

Per completare la agosto risposta, una possibile implementazione della funzione proposta (vedi Delegato di UITextField ).

Non ho testato il codice domness , ma il mio non si blocca se l'utente ha raggiunto il limite ed è compatibile con una nuova stringa che viene sostituita con una più piccola o uguale.

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

Non puoi farlo direttamente - UITextField non ha alcun attributo maxLength , ma puoi impostare il UITextField's delegato, quindi usare:

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

Spesso hai più campi di input con una lunghezza diversa.

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

Il modo migliore sarebbe quello di impostare una notifica sulla modifica del testo. Nel tuo -awakeFromNib del tuo metodo controller di visualizzazione ti consigliamo:

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

Quindi nella stessa classe aggiungi:

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

Quindi collega l'outlet myTextField al tuo UITextField e non ti permetterà di aggiungere altri caratteri dopo aver raggiunto il limite. Assicurati di aggiungere questo al tuo metodo dealloc:

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

Ho creato questo sottoclasse UITextFieldLimit:

  • Più campi di testo supportati
  • Imposta il limite di lunghezza del testo
  • Prevenzione incolla
  • Visualizza un'etichetta di caratteri a sinistra all'interno del campo di testo, che viene nascosta quando si interrompe la modifica.
  • Scuoti l'animazione quando non sono rimasti caratteri.

Prendi UITextFieldLimit.h e UITextFieldLimit.m da questo repository GitHub:

https://github.com/JonathanGurebo/UITextFieldLimit

e inizia a provare!

Contrassegna UITextField creato dallo storyboard e collegalo alla mia sottoclasse utilizzando Identity Inspector:

Ispettore identità

Quindi è possibile collegarlo a un IBOutlet e impostare il limite (il valore predefinito è 10).


Il file ViewController.h deve contenere: (se non si desidera modificare l'impostazione, come il limite)

#import "UITextFieldLimit.h"

/.../

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

Il tuo file ViewController.m dovrebbe @synthesize textFieldLimit.


Imposta il limite di lunghezza del testo nel tuo file 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.
}

Spero che la lezione ti aiuti. Buona fortuna!

Questo dovrebbe essere sufficiente per risolvere il problema (sostituire 4 con il limite desiderato). Assicurati di aggiungere un delegato in IB.

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

Simulo l'effettiva sostituzione della stringa che sta per accadere per calcolare la lunghezza della stringa 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;
}

Versione Swift 3 // ***** NON funzionerà con Swift 2.x! ***** //

Innanzitutto crea un nuovo file Swift: TextFieldMaxLength.swift, e quindi aggiungi il codice qui sotto:

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

e poi vedrai nello Storyboard un nuovo campo (Lunghezza massima) quando selezioni un campo di testo

se hai ancora domande, consulta questo link: http://www.globalnerdy.com/2016/05/18/ios-programming-trick-how- set-a-text-campi-massimo-lunghezza da usare Xcode-to--studio-stile visivo /

Usando Interface builder puoi collegare e ottenere l'evento per " Modifica cambiata " in una qualsiasi delle tue funzioni. Ora puoi inserire la lunghezza

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

}

Il seguente codice è simile alla risposta di sickp ma gestisce correttamente le operazioni di copia-incolla. Se si tenta di incollare un testo più lungo del limite, il codice seguente troncherà il testo per adattarlo al limite invece di rifiutare completamente l'operazione di incollaggio.

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

Per farlo funzionare con cut & amp; incolla di stringhe di qualsiasi lunghezza, suggerirei di cambiare la funzione in qualcosa del tipo:

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

Esiste soluzione generica per impostare la lunghezza massima in Swift. Con IBInspectable puoi aggiungere un nuovo attributo in Xcode Attribute Inspector.  inserisci qui la descrizione dell'immagine

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
    }

}

Swift 2.0 +

Innanzitutto crea una classe per questo processo. Chiamiamolo StringValidator.swift.

Quindi incolla semplicemente il seguente codice al suo interno.

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
}

}

Ora salva la classe .....

Utilizzo ..

Ora vai alla tua classe viewController.swift e rendi le prese del tuo campo di testo come ..

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

Ora vai al metodo shouldChangeCharactersInRange del campo di testo e usa come il seguente.

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
    }

}

Non dimenticare di impostare il protocollo / i metodi delegati dei campi di testo.

Lasciami spiegare questo ... Sto usando il semplice processo di estensione della stringa che ho scritto all'interno di un'altra classe. Ora sto solo chiamando quei metodi di estensione da un'altra classe dove ne ho bisogno aggiungendo check e valore massimo.

Caratteristiche ...

  1. Imposta il limite massimo di un determinato campo di testo.
  2. Imposta il tipo di chiavi accettate per un particolare campo di testo.

I ...

IncludesOnlyCharactersIn // Accetta solo caratteri.

contieneCaratteriIn // Accetta la combinazione di caratteri

doesNotContainsCharactersIn // Non accetta caratteri

Spero che questo abbia aiutato ... Grazie ..

swift 3.0

Questo codice funziona bene quando si incolla la stringa oltre i limiti dei caratteri.

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
    }

Grazie per i tuoi voti. :)

Fornisco una risposta supplementare basata su @Frouo. Penso che la sua risposta sia il modo più bello. Perché è un controllo comune che possiamo riutilizzare.

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
    }

}

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
}

Utilizza l'estensione sottostante per impostare la lunghezza massima dei caratteri di UITextField e 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
    }
}

Puoi impostare il limite di seguito.

 inserisci qui la descrizione dell'immagine

Questo è il modo corretto di gestire la lunghezza massima su UITextField, consente al tasto Invio di uscire dalle dimissioni del campo di testo come primo risponditore e consente all'utente di tornare indietro quando raggiungono il limite

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

Per Xamarin:

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

Altre risposte non gestiscono il caso in cui l'utente può incollare una lunga stringa dagli appunti. Se incollo una stringa lunga, dovrebbe essere troncata ma mostrata. Usa questo nel tuo delegato:

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'

}

È arrivato a 1 riga di codice :)

Imposta il delegato della vista di testo su " self " quindi aggiungi <UITextViewDelegate> nel tuo .h e il seguente codice nel tuo .m .... puoi regolare il numero " 7 " per essere quello che vuoi sia il tuo MASSIMO numero di personaggi.

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

Questo codice spiega la digitazione di nuovi caratteri, l'eliminazione di caratteri, la selezione di caratteri, quindi la digitazione o l'eliminazione, la selezione di caratteri e il taglio, l'incollaggio in generale e la selezione di caratteri e incollaggio.

Fatto!



In alternativa, un altro ottimo modo per scrivere questo codice con operazioni a bit sarebbe

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

Ho aperto una sottoclasse UITextField, STATextField , che offre questa funzionalità (e molto altro) con la sua maxCharacterLength proprietà.

ora quanti caratteri vuoi solo danno valori

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

Usa questo codice qui RESTRICTED_LENGTH è la lunghezza che vuoi limitare per il campo di testo.

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

}

L'ho fatto in Swift per un limite di 8 caratteri quando si utilizza un tastierino numerico.

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

Ho dovuto testare la stringa! = " " per consentire al pulsante Elimina di funzionare sul tastierino numerico, altrimenti non consentirebbe l'eliminazione dei caratteri nel campo di testo dopo che ha raggiunto il massimo

Ho implementato un'estensione UITextField per aggiungere una proprietà maxLength ad essa.

È basato su Xcode 6 IBInspectables, quindi puoi impostare il limite maxLength sul builder Interface.

Ecco l'implementazione:

  

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

Se il tuo scopo di limitare il conteggio del testo è quello di garantire che il testo si adatti a un UILabel altrove, eviterei di usare il conteggio dei caratteri. Si rompe con alcune emoji (il tentativo di troncare un'emoji di doppia dimensione probabilmente bloccherà la tua app). È anche un problema con alcune lingue come il giapponese e il cinese, che hanno un processo di input in due fasi in cui un semplice conteggio non funzionerà.

Ho creato una sottoclasse drop-in UITextField ( MPC_CharacterLimitedTextField su github ). Gli dai la larghezza dell'etichetta di output prevista e gestirà tutte le lingue, le emoji e i problemi di incollaggio. Raccoglierà solo quanti personaggi completi si adatteranno all'etichetta, indipendentemente dal conteggio dei personaggi. C'è una demo nel progetto in modo da poterlo testare per vedere se è quello che ti serve. Spero che possa aiutare chiunque abbia avuto gli stessi problemi con la lunghezza dell'output di me.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top