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.


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


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

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

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

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

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

Chociaż zrobiłem to, aby usunąć błędy> myTextField.text = [myTextField.text substringToIndex: limit];
— Łukasz

11

Utworzyłem tę 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!


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

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


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

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 /


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

}

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

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
    }

}

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

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
}

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


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. :)


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
    }

}

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

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)

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'

}

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

1

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


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

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;

}

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.


1

W przypadku Xamarin:

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.