Ustaw maksymalną długość znaku pola UITextField

Odpowiedzi:

1029

Chociaż UITextFieldklasa nie ma właściwości maksymalnej długości, uzyskanie tej funkcji jest stosunkowo proste, ustawiając pola tekstowe delegatei implementując następującą metodę delegowania:

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

Szybki

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
}

Przed zmianą pola tekstowego UITextField pyta delegata, czy określony tekst powinien zostać zmieniony. Pole tekstowe nie zmieniło się w tym momencie, więc bierzemy jego bieżącą długość i długość łańcucha, który wstawiamy (przez wklejenie skopiowanego tekstu lub wpisanie pojedynczego znaku za pomocą klawiatury), minus długość zakresu. Jeśli ta wartość jest za długa (więcej niż 25 znaków w tym przykładzie), zwróćNO aby zabronić zmiany.

Podczas wpisywania pojedynczego znaku na końcu pola tekstowego range.locationbędzie to długość bieżącego pola i range.lengthbędzie wynosić 0, ponieważ niczego nie zastępujemy / nie usuwamy. Wstawienie do środka pola tekstowego oznacza po prostu inny range.location, a wklejenie wielu znaków oznacza po prostu stringwięcej niż jeden znak.

Usuwanie pojedynczych znaków lub wycinanie wielu znaków określa a range o niezerowej długości i pustym ciągu. Zastąpienie to tylko usunięcie zakresu niepustym ciągiem.

Uwaga na temat zawieszającego się błędu „cofnij”

Jak wspomniano w komentarzach, istnieje błąd, UITextFieldktóry może doprowadzić do awarii.

Jeśli wkleisz w polu, ale implementacja sprawdzania poprawności nie pozwala na wklejeniu, operacja wklejania jest nadal rejestrowana w buforze cofania aplikacji. Jeśli następnie zwolnić cofania (przez potrząsanie urządzeniem i potwierdzenia Cofnij), przy czym UITextFieldbędzie próbował zastąpić ciąg ona myśli , że wklejony w sobie z pustym ciągiem. To się zawiesi, ponieważ nigdy tak naprawdę nie jest wkleiło łańcucha w siebie. Spróbuje zastąpić część łańcucha, która nie istnieje.

Na szczęście możesz uchronić się UITextFieldprzed samobójstwem w ten sposób. Musisz tylko upewnić się, że zakres, który proponuje zastąpić , istnieje w jego bieżącym ciągu. To właśnie robi powyższa wstępna kontrola poczytalności.

swift 3.0 z kopiowaniem i wklejaniem działa poprawnie.

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
    }

Mam nadzieję, że to ci pomoże.

chory
źródło
7
Znajdź rozwiązanie, otaczając te 2 wiersze if (textField == _ssn) {} i dodając return YES; na końcu metody, która pozwoli wszystkim innym UITextFields na akceptację tekstu bez żadnych ograniczeń. Sprytne!
Kyle Clegg,
55
Dobra odpowiedź, ale operator trójskładnikowy jest zbyteczny; można po prostu powiedziećreturn newLength <= 25;
jowie
2
Co jeśli po prostu chcesz, aby tekst nie rozlewał się po ramce pola tekstowego; nie wszystkie znaki mają tę samą szerokość, prawda?
Morkrom
2
Naprawdę występuje błąd cofania, jak wspomina @bcherry - testowany UITextFieldna iPadzie iOS 8.1. (+1 do komentarza). Czy autor dodałby coś na ten temat, ponieważ jest to najwyżej oceniana odpowiedź? Z przyjemnością dokonam edycji, ale moja regularnie wydaje się być odrzucana! :-)
Benjohn
8
@bherry W Swift sprawdzenie, czy sprawa cofania wydaje się przerywać wprowadzanie emoji. Czy liczba (textField.text) nie powinna być faktycznie liczona (textField.text.utf16), aby pasowała do raportowania objc / uikit w zakresie (w porównaniu z wariantem Swift polegającym na liczeniu na łańcuchy)?
rcw3
62

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

Edycja: naprawiono problem wycieku pamięci.

wprowadź opis zdjęcia tutaj

frouo
źródło
Świetny pomysł Frouo! Rozszerzyłem ją w mojej odpowiedzi, aby przenieść przycinanie maxLength do rozszerzenia String, aby można było go również używać do takich rzeczy, jak instancje UITextView, i dodać funkcję wygody, aby skorzystać z tych rozszerzeń String w rozszerzeniu UITextField.
Scott Gardner
1
Czy ta zmienna globalna nie powoduje wycieków pamięci, przechowując odwołania do wszystkich
widoków tekstu
3
@ Ixx Zrobiłem edycję, aby naprawić problem wycieku pamięci, który wskazałeś + szybkie 3. Dzięki
frouo
1
najpiękniejszy sposób na osiągnięcie tego! Dzięki
Victor Choy,
czy ktoś może podać mi jego obiektywną wersję
MRizwan33
56

Dziękuję sierpień! ( Post )

Oto kod, z którym ostatecznie skończyłem:

#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
źródło
19
Niestety to rozwiązanie nie powstrzymuje użytkowników przed kopiowaniem i wklejaniem do pola tekstowego, co pozwala im ominąć limit. Odpowiedź Sickpei poprawnie radzi sobie z tą sytuacją.
Ant
5
Co się dzieje z ludźmi, którzy mają instrukcję if, aby zwrócić NIE lub TAK? Spróbuj tego: return! (TextField.text.length> = MAX_LENGTH && range.length == 0);
Matt Parkins,
lub toreturn textField.text.length < MAX_LENGTH || range.length != 0;
igrek
22

Aby uzupełnić sierpniową odpowiedź, możliwa implementacja proponowanej funkcji (patrz delegat UITextField ).

Nie testowałem kodu domeny , ale mój nie blokuje się , jeśli użytkownik osiągnął limit, i jest zgodny z nowym ciągiem, który zastępuje mniejszy lub równy.

-(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
źródło
17

Nie możesz tego zrobić bezpośrednio - UITextFieldnie ma atrybutu maxLength , ale możesz ustawić UITextField'sdelegata, a następnie użyć:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
sierpień
źródło
5
Zgadzam się, jest to najlepszy sposób, ale pozostaje trochę hack. Prześlij do Apple raport o błędzie, że chcesz zobaczyć właściwość o długości tekstu. Zdecydowanie mnie to również interesuje.
awokada
5
@avocade, to nie hack: to przykład, w którym musisz zrobić podstawowy kod frameworka, który Apple powinien dla Ciebie zrobić. Istnieje wiele przykładów tego w zestawie iOS SDK.
Dan Rosenstark,
13

Często masz wiele pól wprowadzania o innej długości.

- (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
źródło
12

Najlepszym sposobem byłoby skonfigurowanie powiadomienia o zmianie tekstu. W -awakeFromNibmetodzie kontrolera widoku będziesz chciał:

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

Następnie w tej samej klasie dodaj:

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

Następnie podłącz ujście myTextFielddo swojego, UITextFielda nie pozwoli ci dodać więcej znaków po osiągnięciu limitu. Dodaj to do metody dealloc:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UITextFieldTextDidChangeNotification" object:myTextField];
Martin Pilkington
źródło
Chociaż zrobiłem to, aby usunąć błędy> myTextField.text = [myTextField.text substringToIndex: limit];
Łukasz
11

Utworzyłem podklasę UITextFieldLimit:

  • Obsługiwanych jest wiele pól tekstowych
  • Ustaw limit długości tekstu
  • Zapobieganie wklejaniu
  • Wyświetla etykietę lewych znaków w polu tekstowym, ukryj się po zakończeniu edycji.
  • Wstrząśnij animacją, gdy nie pozostały żadne postacie.

Pobierz UITextFieldLimit.hi UITextFieldLimit.mz tego repozytorium GitHub:

https://github.com/JonathanGurebo/UITextFieldLimit

i zacznij testować!

Oznacz utworzony przez użytkownika scenariusz UITextField i połącz go z moją podklasą za pomocą Inspektora tożsamości:

Inspektor tożsamości

Następnie możesz połączyć go z IBOutlet i ustawić limit (domyślnie jest to 10).


Twój plik ViewController.h powinien zawierać: (jeśli nie chcesz modyfikować ustawienia, np. Limitu)

#import "UITextFieldLimit.h"

/.../

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

Twój plik ViewController.m powinien @synthesize textFieldLimit.


Ustaw limit długości tekstu w pliku 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.
}

Mam nadzieję, że klasa ci pomoże. Powodzenia!

Jonathan Gurebo
źródło
Ze względu na małą potrzebę limitu postaci, myślę, że dodanie swojej klasy byłoby po prostu przesadą.
Domness
Wciąż doceniany wysiłek.
Reaper
11

To powinno wystarczyć do rozwiązania problemu (zamień 4 na żądany limit). Pamiętaj tylko, aby dodać delegata w IB.

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

Użyj poniższego rozszerzenia, aby ustawić maksymalną długość znaków a UITextFieldi 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
        }
    }

Możesz ustawić limit poniżej.

wprowadź opis zdjęcia tutaj

COVID-19
źródło
jak dotąd najlepsza odpowiedź ,,, wielkie dzięki świetne rozwiązanie, gdy istnieje wiele pól tekstowych, które wymagają różnych długości
Carlos Norena
Naprawdę świetne rozwiązanie dla limitu wprowadzania znaków w polu tekstowym i kontroli tekstu. Zapisano linie kodu i czas dla programistów ... :)
Sandip Patel - SM
Działa to lepiej niż inne rozwiązania, które znalazłem. Na przykład, jeśli masz emoji w polu tekstowym, inne rozszerzenia, które znalazłem, przeskakiwałyby na koniec linii podczas edycji. Ale twój kod tego nie robi. Dzięki!
Phontaine Judd
7

Symuluję faktyczną zamianę ciągu, która ma się wydarzyć, aby obliczyć długość przyszłego łańcucha:

- (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
źródło
7

Wersja Swift 3 // ***** To NIE będzie działać z Swift 2.x! ***** //

Najpierw utwórz nowy plik Swift: TextFieldMaxLength.swift, a następnie dodaj poniższy kod:

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

a po wybraniu dowolnego pola tekstowego zobaczysz w Storyboard nowe pole (Maksymalna długość)

jeśli nadal masz więcej pytań, sprawdź ten link: http://www.globalnerdy.com/2016/05/18/ios-programming-trick-how-to-use-xcode-to-set-a-text-fields -maksymalna długość-wizualny-styl-studio /

Gilad Brunfman
źródło
Ostrzeżenie: ta zmienna globalna powoduje wycieki pamięci, przechowując odniesienia do wszystkich widoków tekstu.
frouo
6

Za pomocą konstruktora interfejsów możesz połączyć i uzyskać zdarzenie „Edycja zmieniona” w dowolnej funkcji. Teraz możesz sprawdzić długość

- (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
źródło
6

Poniższy kod jest podobny do odpowiedzi sickp, ale obsługuje poprawnie operacje kopiuj-wklej. Jeśli spróbujesz wkleić tekst, który jest dłuższy niż limit, poniższy kod skróci tekst, aby dopasować go do limitu, zamiast całkowicie odmawiać operacji wklejania.

- (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
źródło
6

Istnieje ogólne rozwiązanie do ustawiania maksymalnej długości w Swift. Przez IBInspectable możesz dodać nowy atrybut w Inspektorze atrybutów Xcode.wprowadź opis zdjęcia tutaj

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
    }

}
Dzierżawa
źródło
Czyste i idealne rozwiązanie
Eduardo
Trzymanie pola UITextField w polu globalnym zachowa je w pamięci nawet po zamknięciu kontrolera UIViewController. To jest wyciek pamięci. Nie używaj tej metody.
Gunhan
5

Aby działało z wycinaniem i wklejaniem ciągów dowolnej długości, sugerowałbym zmianę funkcji na coś takiego:

#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
źródło
4

Szybki 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
źródło
Dlaczego guard?
oddRaven
sprawdź, czy tekst jest zerowy, jeśli chcesz, możesz również użyć if @oddRaven
Shan Ye
3

Swift 2.0 +

Przede wszystkim utwórz klasę dla tego procesu. Nazwijmy to StringValidator.swift.

Następnie wklej do niego następujący kod.

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
}

}

Teraz uratuj klasę .....

Stosowanie..

Teraz przejdź do klasy viewController.swift i spraw, aby ujścia twojego pola tekstowego były ...

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

Teraz przejdź do metody textChangeCharactersInRange pola tekstowego i użyj jej w następujący sposób.

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
    }

}

Nie zapomnij ustawić protokołu delegowanego / metod pól tekstowych.

Pozwól mi wyjaśnić na ten temat ... Korzystam z prostego procesu rozszerzenia łańcucha napisanego wewnątrz innej klasy. Teraz po prostu wywołuję te metody rozszerzenia z innej klasy, w której ich potrzebuję, dodając check i maksymalną wartość.

Funkcje...

  1. Ustawi maksymalny limit dla konkretnego pola tekstowego.
  2. Ustawi typ akceptowanych kluczy dla konkretnego pola tekstowego.

Rodzaje ...

zawieraOnlyCharactersIn // Akceptuje tylko znaki.

zawieraCharactersIn // Akceptuje kombinację znaków

doesNotContainsCharactersIn // Nie przyjmuje znaków

Mam nadzieję, że to pomogło .... Dzięki ..

po zakończeniu
źródło
3

szybki 3.0

Ten kod działa dobrze, gdy wklejasz ciąg znaków ponad limity znaków.

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
    }

Dziękuję za twoje głosy. :)

Ilesh P.
źródło
2
UITextField, a nie UITextView.
Jonny
3

Udzielam dodatkowej odpowiedzi na podstawie @Frouo. Myślę, że jego odpowiedź jest najpiękniejsza. Ponieważ jest to powszechna kontrola, której możemy użyć ponownie.

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
źródło
2

Jest to poprawny sposób obsługi maksymalnej długości na UITextField, pozwala klawiszowi powrotu na wyjście z rezygnacji z pola tekstowego jako pierwszej odpowiedzi i pozwala użytkownikowi cofnąć się, gdy osiągną limit

- (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
źródło
2

Co z tym prostym podejściem? Dla mnie działa dobrze.

extension UITextField {

    func  charactersLimit(to:Int) {

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

Następnie:

someTextField.charactersLimit(to:16)
Joaquin Pereira
źródło
1

Inne odpowiedzi nie obsługują przypadku, w którym użytkownik może wkleić długi ciąg ze schowka. Jeśli wkleję długi ciąg, powinien on zostać obcięty, ale pokazany. Użyj tego w swoim delegacie:

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
źródło
1

Zrobiłem to do 1 linii kodu :)

Ustaw delegata widoku tekstowego na „jaźń”, a następnie dodaj <UITextViewDelegate>.h i następujący kod w .m .... możesz dostosować liczbę „7”, aby była taka, jaka ma być MAKSYMALNA liczba znaków.

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

Ten kod uwzględnia wpisywanie nowych znaków, usuwanie znaków, wybieranie znaków, a następnie pisanie lub usuwanie, wybieranie znaków i wycinanie, ogólnie wklejanie oraz wybieranie znaków i wklejanie.

Gotowy!






Alternatywnie byłby inny fajny sposób na napisanie tego kodu za pomocą operacji bitowych

-(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
źródło
1

Otworzyłem podklasę UITextField, STATextField , która oferuje tę funkcjonalność (i wiele więcej) dzięki swojej maxCharacterLengthwłaściwości.

Szlagier
źródło
1

teraz ile znaków chcesz podać wartości

 - (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
źródło
1

Użyj tego kodu tutaj RESTRICTED_LENGTH to długość, którą chcesz ograniczyć dla pola tekstowego.

   - (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
źródło
1

Zrobiłem to w Swift dla limitu 8 znaków, używając klawiatury numerycznej.

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

Musiałem przetestować ciąg! = "", Aby umożliwić działanie przycisku usuwania na klawiaturze numerycznej, w przeciwnym razie nie pozwoliłby na usuwanie znaków w polu tekstowym po osiągnięciu maksymalnego poziomu.

u84six
źródło
1

W przypadku Xamarin:

YourTextField.ShouldChangeCharacters = 
delegate(UITextField textField, NSRange range, string replacementString)
        {
            return (range.Location + replacementString.Length) <= 4; // MaxLength == 4
        };
Kedu
źródło
1

Zaimplementowałem rozszerzenie UITextField, aby dodać do niego właściwość maxLength.

Jest oparty na Xcode 6 IBInspectables, więc możesz ustawić limit maksymalnej długości w Konstruktorze interfejsu.

Oto implementacja:

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
źródło