Defina o comprimento máximo de caracteres de um UITextField

Respostas:

1029

Embora a UITextFieldclasse não tenha propriedade de tamanho máximo, é relativamente simples obter essa funcionalidade, definindo os campos de texto delegatee implementando o seguinte método delegado:

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

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 o campo de texto mudar, o UITextField pergunta ao delegado se o texto especificado deve ser alterado. O campo de texto não mudou neste momento; portanto, pegamos o comprimento atual e o comprimento da string que estamos inserindo (colando o texto copiado ou digitando um único caractere usando o teclado), menos o comprimento do intervalo. Se esse valor for muito longo (mais de 25 caracteres neste exemplo), retorne NOpara proibir a alteração.

Ao digitar um único caractere no final de um campo de texto, range.locationserá o comprimento do campo atual e range.lengthserá 0 porque não estamos substituindo / excluindo nada. Inserir no meio de um campo de texto significa apenas um diferente range.location, e colar vários caracteres significa que stringpossui mais de um caractere.

A exclusão de caracteres únicos ou o corte de vários caracteres é especificada por a rangecom um comprimento diferente de zero e uma sequência vazia. A substituição é apenas uma exclusão de intervalo com uma sequência não vazia.

Uma observação sobre o erro "desfazer"

Como é mencionado nos comentários, há um erro UITextFieldque pode levar a uma falha.

Se você colar no campo, mas a pasta for impedida pela implementação da validação, a operação de colar ainda será registrada no buffer de desfazer do aplicativo. Se você desfazer uma ação (agitando o dispositivo e confirmando um Desfazer), a UITextFieldtentativa tentará substituir a cadeia que ela acha que colou nela mesma com uma cadeia vazia. Isso irá travar porque nunca realmente colou a string nela mesma. Ele tentará substituir uma parte da string que não existe.

Felizmente, você pode proteger-se UITextFieldde se matar assim. Você só precisa garantir que a gama que propõe a substituição faz existir dentro de sua seqüência atual. É isso que a verificação de sanidade inicial acima faz.

Swift 3.0 com copiar e colar funcionando bem.

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 seja útil para você.

doente
fonte
7
Encontre uma solução envolvendo essas 2 linhas com if (textField == _ssn) {} e adicionando return YES; no final do método, o que permitirá que todos os outros UITextFields aceitem texto sem nenhuma restrição. Bacana!
Kyle Clegg
55
Boa resposta, mas o operador ternário é supérfluo; você poderia colocarreturn newLength <= 25;
jowie
2
E se você apenas quiser que o texto não se espalhe sobre o quadro do campo de texto; nem todos os caracteres têm a mesma largura, certo?
Morkrom
2
Realmente há um erro de desfazer como o @bcherry menciona - testado UITextFieldno iPad iOS 8.1. (+1 para comentar). O autor adicionaria algo sobre isso, pois é a resposta mais votada? Fico feliz em fazer uma edição, mas as minhas parecem ser rejeitadas regularmente! :-)
Benjohn 24/11
8
@bherry No Swift, a verificação do caso de desfazer parece interromper a entrada de emoji. A contagem (textField.text) não deveria realmente ser count (textField.text.utf16) para corresponder aos relatórios objc / uikit no intervalo (versus a variante de Swift da contagem de strings)?
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
    }
}

Edição: problema de vazamento de memória corrigido.

insira a descrição da imagem aqui

frouo
fonte
Ótima idéia Frouo! Eu a expandi na minha resposta para mover o corte maxLength para uma extensão String, para que ele também possa ser usado para coisas como instâncias UITextView e para adicionar uma função de conveniência para tirar proveito dessas extensões String em uma extensão UITextField.
Scott Gardner
1
Não esta variável global criar vazamentos de memória, mantendo referências a todos os TextViews (que referenciam os superviews até raiz-)
Ixx
3
@Ixx Eu editei para corrigir o problema de fuga de memória que você apontou + rápida 3. Graças
frouo
1
a maneira mais bonita de conseguir isso! Obrigado
Victor Choy
Alguém pode me fornecer sua versão objetivo
MRizwan33
56

Obrigado agosto! ( Post )

Este é o código que eu acabei com o qual 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
fonte
19
Infelizmente, esta solução falha ao impedir que os usuários copiem e colem em um campo de texto, permitindo que eles ultrapassem o limite. A resposta do grão-de-bico lida com essa situação corretamente.
Ant
5
O que há com pessoas que possuem uma declaração if para retornar NO ou YES? Tente isso: return! (TextField.text.length> = MAX_LENGTH && range.length == 0);
Matt Parkins
ou issoreturn textField.text.length < MAX_LENGTH || range.length != 0;
igrek 21/11
22

Para concluir a resposta de agosto , uma possível implementação da função proposta (consulte o representante do UITextField ).

Eu não testei o código de domínio, mas o meu não fica preso se o usuário atingir o limite e é compatível com uma nova string que substitui uma menor ou 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
fonte
17

Você não pode fazer isso diretamente - UITextFieldnão tem atributo maxLength , mas pode definir o UITextField'sdelegado e usar:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
agosto
fonte
5
Concordo, este é o melhor caminho a seguir, mas permanece um pouco complicado. Envie à Apple um relatório de bug que você gostaria de ver uma propriedade para o tamanho do texto. Eu definitivamente estou interessado nisso também.
avocade 12/01/09
5
@avocade, não é um truque: é um exemplo em que você precisa criar um código de estrutura básico que a Apple deveria ter feito por você. Existem muitos exemplos disso no SDK do iOS.
Dan Rosenstark
13

Muitas vezes você tem vários campos de entrada com um comprimento 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
fonte
12

A melhor maneira seria configurar uma notificação sobre a alteração do texto. No seu -awakeFromNibmétodo de controle de exibição, você deseja:

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

Em seguida, na mesma classe, adicione:

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

Em seguida, conecte a tomada myTextFieldà sua UITextFielde ela não permitirá que você adicione mais caracteres depois de atingir o limite. Certifique-se de adicionar isso ao seu método de desalocação:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UITextFieldTextDidChangeNotification" object:myTextField];
Martin Pilkington
fonte
Embora eu tenha feito isso para remover erros> myTextField.text = [myTextField.text substringToIndex: limit];
Lucas
11

Eu criei esta subclasse UITextFieldLimit:

  • Vários campos de texto suportados
  • Defina o limite de comprimento do texto
  • Prevenção de pasta
  • Exibe um rótulo de caracteres esquerdos dentro do campo de texto, fica oculto quando você para de editar.
  • Agite a animação quando não houver caracteres.

Pegue o UITextFieldLimit.he UITextFieldLimit.mdeste repositório do GitHub:

https://github.com/JonathanGurebo/UITextFieldLimit

e comece a testar!

Marque o UITextField criado pelo storyboard e vincule-o à minha subclasse usando o Identity Inspector:

Inspetor de identidade

Em seguida, você pode vinculá-lo a um IBOutlet e definir o limite (o padrão é 10).


Seu arquivo ViewController.h deve conter: (se você não quiser modificar a configuração, como o limite)

#import "UITextFieldLimit.h"

/.../

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

Seu arquivo ViewController.m deve @synthesize textFieldLimit.


Defina o limite de comprimento do texto no seu arquivo 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 a classe ajude você. Boa sorte!

Jonathan Gurebo
fonte
Para a pequena necessidade do limite de caracteres, acho que adicionar sua classe seria apenas um exagero.
187 Domness
Ainda esforço apreciado.
Reaper
11

Isso deve ser suficiente para resolver o problema (substitua 4 pelo limite que você deseja). Apenas certifique-se de adicionar delegado no IB.

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

Use a extensão abaixo para definir o comprimento máximo de caracteres de a UITextFielde 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
        }
    }

Você pode definir o limite abaixo.

insira a descrição da imagem aqui

COVID-19
fonte
melhor resposta de longe ,,, graças uma solução muito grande quando há muitos campos de texto que precisam de diferentes comprimentos
Carlos Norena
Solução realmente excelente para o campo de texto e o limite de entrada de caracteres de controle de visualização de texto. Sua economia de linhas de código e tempo também para desenvolvedor ... :)
Sandip Patel - SM
Isso funciona melhor do que as outras soluções que encontrei. Por exemplo, se você tiver emojis no seu campo de texto, outras extensões que encontrei pulariam para o final da linha durante a edição. Mas seu código não faz isso. Obrigado!
Phontaine Judd 31/12/19
7

Eu simulo a substituição real da string que está prestes a calcular o tamanho da string 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
fonte
7

Versão Swift 3 // ***** Isso NÃO funcionará com o Swift 2.x! ***** //

Primeiro, crie um novo arquivo Swift: TextFieldMaxLength.swift e adicione o código abaixo:

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, no Storyboard, você verá um novo campo (Comprimento máximo) ao selecionar qualquer Campo de texto

se você ainda tiver mais perguntas, consulte este link: 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
fonte
Atenção, essa variável global cria vazamentos de memória, mantendo referências a todas as visualizações de texto.
frouo
6

Usando o construtor Interface, você pode vincular e obter o evento para "Edição alterada" em qualquer uma das suas funções. Agora você pode colocar o cheque pelo comprimento

- (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
fonte
6

O código a seguir é semelhante à resposta do sickp, mas lida com operações de copiar e colar corretamente. Se você tentar colar um texto maior que o limite, o código a seguir truncará o texto para que ele se ajuste ao limite, em vez de recusar completamente a operação de colar.

- (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
fonte
6

Existe uma solução genérica para definir o comprimento máximo no Swift. Por IBInspectable, você pode adicionar um novo atributo no Xcode Attribute Inspector.insira a descrição da imagem aqui

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
fonte
Solução limpa e perfeita
Eduardo
Manter um UITextField em um campo global os manterá na memória mesmo depois que o UIViewController for descartado. Este é um vazamento de memória. Não use esse método.
Gunhan 27/02/19
5

Para fazê-lo funcionar com recortar e colar cordas de qualquer comprimento, sugiro alterar a função para 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
fonte
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
fonte
Por que o guard?
precisa saber é o seguinte
verificar se o texto é nulo, se você quiser, você também pode usar se @oddRaven
Shan Ye
3

Swift 2.0 +

Antes de tudo, crie uma classe para esse processo. Vamos chamá-lo de StringValidator.swift.

Em seguida, basta colar o seguinte código dentro dele.

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
}

}

Agora salve a turma .....

Uso..

Agora vá para a classe viewController.swift e faça as saídas do seu campo de texto como ..

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

Agora vá para o método shouldChangeCharactersInRange do campo de texto e use como o seguinte.

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ão se esqueça de definir o protocolo / métodos de delegação de campos de texto.

Deixe-me explicar sobre isso ... Estou usando o processo simples de extensão de string que escrevi dentro de outra classe. Agora, estou apenas chamando esses métodos de extensão de outra classe em que preciso deles, adicionando cheque e valor máximo.

Recursos...

  1. Ele definirá o limite máximo de um campo de texto específico.
  2. Ele definirá o tipo de chaves aceitas para um campo de texto específico.

Tipos ...

containsOnlyCharactersIn // Aceita apenas caracteres.

containsCharactersIn // Aceita combinação de caracteres

doesNotContainsCharactersIn // Não aceita caracteres

Espero que isso tenha ajudado .... Obrigado ..

onCompletion
fonte
3

swift 3.0

Este código está funcionando bem quando você cola a string mais do que os limites de caracteres.

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
    }

Obrigado por seus votos. :)

Ilesh P
fonte
2
UITextField, não UITextView.
Jonny
3

Dou uma resposta complementar com base no @Frouo. Eu acho que a resposta dele é a maneira mais bonita. Porque é um controle comum 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
fonte
2

Esta é a maneira correta de lidar com o comprimento máximo no UITextField, permite que a tecla de retorno saia da renúncia do campo de texto como primeiro respondedor e permite que o usuário volte ao espaço quando atingir o 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;
    }
}
anders
fonte
2

E essa abordagem simples. Está funcionando bem para mim.

extension UITextField {

    func  charactersLimit(to:Int) {

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

Então:

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

Outras respostas não tratam do caso em que o usuário pode colar uma cadeia longa da área de transferência. Se eu colar uma string longa, ela deve ser truncada, mas mostrada. Use isso em seu 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
fonte
1

Reduzi a 1 linha de código :)

Defina o delegado da sua exibição de texto como "self" e adicione o <UITextViewDelegate>.he o seguinte código no seu .m .... você pode ajustar o número "7" para o que você deseja que seu número MÁXIMO de caracteres seja.

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

Esse código é responsável pela digitação de novos caracteres, exclusão de caracteres, seleção de caracteres e digitação ou exclusão, seleção de caracteres e recorte, colagem em geral e seleção de caracteres e colagem.

Feito!






Como alternativa, outra maneira legal de escrever esse código com operações de bits seria

-(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
fonte
1

Abri de código aberto uma subclasse UITextField, STATextField , que oferece essa funcionalidade (e muito mais) com sua maxCharacterLengthpropriedade.

Stunner
fonte
1

agora quantos caracteres você quer apenas dar 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
fonte
1

Use este código aqui RESTRICTED_LENGTH é o comprimento que você deseja restringir para o 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
fonte
1

Eu fiz isso no Swift por um limite de 8 caracteres ao usar um teclado numérico.

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

Eu tive que testar a string! = "" Para permitir que o botão excluir funcionasse no teclado numérico, caso contrário, não permitiria excluir caracteres no campo de texto depois que atingisse o valor máx.

u84six
fonte
1

Para o Xamarin:

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

Eu implementei uma extensão UITextField para adicionar uma propriedade maxLength a ela.

É baseado no Xcode 6 IBInspectables, para que você possa definir o limite maxLength no construtor Interface.

Aqui está a implementação:

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
fonte