Ogranicz liczbę znaków w uitextview

80

Podaję widok tekstu, aby opublikować jakiś ciąg.

Stosuję następującą metodę, aby ograniczyć liczbę znaków do 140 długości.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
   return [[textView text] length] <= 140;
}

Kod działa dobrze, z wyjątkiem pierwszego warunku, że nie działa backspace. przypuszczam, że osiągnąłem limit 140 znaków, więc metoda da mi fałsz i użytkownik nie może wstawić więcej znaków, ale po tym, gdy próbuję usunąć niektóre znaki, widok tekstu zachowuje się tak, jakby był wyłączony.

Zatem pytanie brzmi: „Jak usunąć znaki z textview.textwidoku tekstu lub ponownie go włączyć?”

harshalb
źródło
Sprawdź tę odpowiedź
Hemang

Odpowiedzi:

67

Zamiast tego powinieneś szukać pustego ciągu, jak mówi odniesienie do jabłka

Jeśli użytkownik naciśnie klawisz Delete, długość zakresu wynosi 1, a pusty obiekt łańcuchowy zastępuje ten pojedynczy znak.

Myślę, że czek, który faktycznie chcesz wykonać, to coś w rodzaju [[textView text] length] - range.length + text.length > 140uwzględnienia operacji wytnij / wklej.

David Gelhar
źródło
dzięki ale może być bardziej szczegółowe Nie rozumiem specyfikacji technicznej jabłka
harshalb
po prostu powiedz mi, co mam umieścić w pierwszym warunku. Robię to przez prawie 4 godziny
ostry
9
Myślę, że czek, który faktycznie chcesz wykonać, to coś w rodzaju [[textView text] length] - range.length + text.length > 140uwzględnienia operacji wytnij / wklej.
David Gelhar,
2
[[textView text] length] - range.length + text.length> 140 powinno wynosić [[textView text] length] - range.length + text.length <140
Kuzon
Kuzon, nie, jeśli domyślnie zwracasz wartość true i chcesz zwrócić wartość false, jeśli przekroczysz limit 140 znaków.
kamień
165
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    return textView.text.length + (text.length - range.length) <= 140;
}

Dotyczy to użytkowników wycinania tekstu lub usuwania ciągów dłuższych niż pojedynczy znak (tj. Jeśli wybierają, a następnie wciskają klawisz Backspace) lub podświetlania zakresu i wklejania ciągów krótszych lub dłuższych od niego.

Wersja Swift 4.0

 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    return textView.text.count + (text.count - range.length) <= 140
}
Tim
źródło
czy to jest IBAction? jak połączyć go z danym TextView jako typy użytkowników?
uczeń
1
Musisz ustawić kontroler widoku jako UITextViewDelegate, a następnie podłączyć właściciela pliku jako delegata widoku tekstu
Tim
Pomyślałem, że byłoby bardziej sprawiedliwie zadać dodatkowe pytanie: Mam problemy z posiadaniem dwóch UITextviews, które wymagają ograniczenia znaków w tym samym kontrolerze. Czy możesz pomóc? stackoverflow.com/questions/25272413/…
uczeń
Powinno to być oznaczone jako poprawna odpowiedź. Dziękuję
Hernan Arber
Spowoduje to awarię, jeśli wkleisz tekst, który jest zbyt długi, aby pasował (dlatego falsezostanie zwrócony), a następnie spróbujesz cofnąć akcję.
Raimundas Sakalauskas
18

dla swift 4:

//MARK:- TextView Delegate
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    //300 chars restriction
    return textView.text.count + (text.count - range.length) <= 300
}
Rohit Sisodia
źródło
10

Jednak możesz również użyć poniższego działającego kodu.

- (void)textViewDidChange:(UITextView *)textView{

    NSInteger restrictedLength=140;

    NSString *temp=textView.text;

    if([[textView text] length] > restrictedLength){
        textView.text=[temp substringToIndex:[temp length]-1];
    }
}
Saroj
źródło
Generalnie nie jest to preferowany sposób edycji czegoś po ustawieniu. Lepiej sprawdź to w „shouldChangeCharactersInRange”, aby zapobiec edycji tekstu.
Benjamin Piette
7

W przypadku Swift 5 i iOS 12 wypróbuj następującą implementację textView(_:shouldChangeTextIn:replacementText:)metody, która jest częścią UITextViewDelegateprotokołu:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    guard let rangeOfTextToReplace = Range(range, in: textView.text) else {
        return false
    }
    let substringToReplace = textView.text[rangeOfTextToReplace]
    let count = textView.text.count - substringToReplace.count + text.count
    return count <= 10
}
  • Najważniejszą częścią tego kodu jest konwersja z range( NSRange) na rangeOfTextToReplace( Range<String.Index>). Obejrzyj ten samouczek wideo, aby zrozumieć, dlaczego ta konwersja jest ważna.
  • Aby to działało poprawnie kod, należy również ustawić textField„s smartInsertDeleteTypewartości UITextSmartInsertDeleteType.no. Zapobiegnie to ewentualnemu wstawieniu (niechcianej) dodatkowej przestrzeni podczas wykonywania operacji wklejania.

Pełny przykładowy kod poniżej pokazuje, jak zaimplementować textView(_:shouldChangeTextIn:replacementText:)w UIViewController:

import UIKit

class ViewController: UIViewController, UITextViewDelegate {

    @IBOutlet var textView: UITextView! // Link this to a UITextView in Storyboard

    override func viewDidLoad() {
        super.viewDidLoad()

        textView.smartInsertDeleteType = UITextSmartInsertDeleteType.no
        textView.delegate = self
    }

    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        guard let rangeOfTextToReplace = Range(range, in: textView.text) else {
            return false
        }
        let substringToReplace = textView.text[rangeOfTextToReplace]
        let count = textView.text.count - substringToReplace.count + text.count
        return count <= 10
    }

}
Imanou Petit
źródło
5

Szybki:

// MARK: UITextViewDelegate

let COMMENTS_LIMIT = 255

func textView(textView: UITextView,  shouldChangeTextInRange range:NSRange, replacementText text:String ) -> Bool {
    return count(comments.text) + (count(text) - range.length) <= COMMENTS_LIMIT;
}
Alexander Volkov
źródło
countElementszostał zastąpiony przez countswift 1.2
Tim Windsor Brown
1
aw Swift 2 musisz wpisać textView.text.characters.count lub dowolne kodowanie: developer.apple.com/swift/blog/?id=30
Heckscheibe
4

z tego

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

    int limit = 139;

    return !([textField.text length]>limit && [string length] > range.length);

}

spowoduje to wprowadzenie tylko 140 znaków i możesz je usunąć w razie potrzeby

B25 Dec
źródło
4

Ogranicz przepełnienie, a nie cały tekst!

Wracając falsew ...shouldChangeTextInRange...metodzie delegata, w rzeczywistości ograniczasz cały tekst, a obsługa następujących sytuacji może być bardzo trudna:

  • Kopiuj i wklejaj
  • Wybierz obszar tekstu i edytuj
  • Korzystanie z automatycznej sugestii
  • Korzystanie z wprowadzania głosowego (polecenie głosowe lub dyktowanie)

Więc możesz:

Po prostu ogranicz przepełnienie tekstu

Usuwając dodatkowe znaki:

textView.text = String(textView.text.prefix(140))

Możesz to zrobić nawet w locie ! umieszczając ten kod wewnątrz działania z textViewlub textFieldz .editingChangedimprezy.

Mojtaba Hosseini
źródło
Umieszczenie tego w delegacie UITextView func textViewDidChange(_ textView: UITextView) {...}działa pięknie, przycinając tylko koniec długo wklejonego tekstu
Josselin
2

Chociaż potrzebowałem if-elsewarunku, więc to zadziałało:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    BOOL status = textView.text.length + (text.length - range.length) <= 15;
    if (status)
    {
        [self.btnShare setEnabled:YES];
        [self.btnShare setAlpha:1];
    }
    else
    {
        [self.btnShare setEnabled:NO];
        [self.btnShare setAlpha:0.25];
    }
    return status;
}

W zasadzie przycisk jest wyłączony. Ale jeśli chcesz, aby użytkownik nie mógł opublikować pustego testu, po prostu umieść warunek na kliknięciu przycisku:

- (void)btnShare_click:(id)sender
{
    NSString *txt = [self.txtShare.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    if ([txt length] == 0)
    {
        [self.btnShare setEnabled:NO];
        [self.btnShare setAlpha:0.25f];
        [[[UIAlertView alloc]initWithTitle:nil message:@"Please enter some text to share." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
        return;
    }
    .
    .
    .
    .
    .
    .
    // rest of your code
}
Vaibhav Saran
źródło
1

Problem z niektórymi odpowiedziami podanymi powyżej jest taki, że na przykład mam pole tekstowe i muszę ustawić limit 15 znaków, a następnie zatrzymuje się po wpisaniu 15 znaku. ale nie pozwalają na usunięcie. Oznacza to, że przycisk usuwania również nie działa. Ponieważ miałem ten sam problem. Wyszedł z rozwiązaniem, podanym poniżej. Działa idealnie dla mnie

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
 if(textField.tag==6)
 {
    if ([textField.text length]<=30)
    {
        return YES;   
    }
    else if([@"" isEqualToString:string])
    {
        textField.text=[textField.text substringToIndex:30 ];
    }

    return NO;
 }
 else
 {
    return YES;
 }
}

Mam pole tekstowe, którego tag ustawiłem na „6” i ograniczyłem maksymalny limit znaków = 30; działa dobrze w każdym przypadku

Jasmeet
źródło
1

Szybka wersja @Tima Gostony'ego:

// restrict the input for textview to 500
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    return count(textView.text) + (count(text) - range.length) <= 500;
}
Michael Shang
źródło
1

Tutaj dążymy do najlepszego dopasowania. Wyświetl liczbę pozostałych znaków: pozostało „n” znaków.

var charCount = 0;
let maxLength = 150
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {

    if text == "" // Checking backspace
    {
        if textView.text.characters.count == 0
        {
            charCount = 0
            characterCount.text = String(format: "%i Characters Left", maxLength - charCount)
            return false
        }
        charCount = (textView.text.characters.count - 1)
        characterCount.text = String(format: "%i Characters Left", maxLength - charCount)
      return true
    }
    else
    {
        charCount = (textView.text.characters.count + 1)
        characterCount.text = String(format: "%i Characters Left", maxLength - charCount)

        if charCount >= maxLength + 1
        {
            charCount = maxLength
            characterCount.text = String(format: "%i Characters Left", maxLength - charCount)
            return false;
        }
    }
    return true
}
Wentylator YSR
źródło
1

Jeśli chcesz również wkleić kod do maksymalnej liczby znaków, jednocześnie odcinając przepełnienie i aktualizując etykietę licznika:

let maxChar: Int
let countLabel: UILabel

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    let oldChar = textView.text.count - range.length
    let oldRemainingChar = maxChar - oldChar
    let newChar = oldChar + text.count
    let newRemainingChar = maxChar - newChar
    let replaceChar = newRemainingChar > 0 ? text.count : oldRemainingChar

    if
        let textRange = textView.textRange(for: range),
        replaceChar > 0 || range.length > 0
    {
        textView.replace(textRange, withText: String(text.prefix(replaceChar)))
        countLabel.text = String(describing: maxChar - textView.text.count)
    }

    return false
}

Z rozszerzeniem:

extension UITextInput {
    func textRange(for range: NSRange) -> UITextRange? {
        var result: UITextRange?

        if
            let start = position(from: beginningOfDocument, offset: range.location),
            let end = position(from: start, offset: range.length)
        {
            result = textRange(from: start, to: end)

        }

        return result
    }
}
Daniel
źródło
1

Wypróbuj to: -

 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    print("chars \(textView.text.count) \( text)")

    if(textView.text.count > 20 && range.length == 0) {
        print("Please summarize in 20 characters or less")
        return false
    }
    return true
}
Abhijeet Mallick
źródło
0

Wpisz poniższy kod w textView:shouldChangeTextInRange:replacementText:metodzie:

if ([textView.text length]>=3 && ![text isEqualToString:@""]) {
    return NO;
}
return YES;
user2493047
źródło
0

Swift5:

let maxChars = 255

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
  if maxChars - aTextView.text.count == 0 {
    if range.length != 1 {
    return false
    }
  }
  return true
}
Gustiin
źródło
0

Użyj poniższego kodu.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    if(text.length == 0)
    {
        return YES;
    }
    else if(self.txtViewComments.text.length > 255)
    {
        return NO;
    }
    else
    {
        return YES;
    }
}
Vikas Grandhi
źródło
jeśli warunek jest używany do usuwania znaków z widoku tekstu
Vikas Grandhi
0

Oto najprostsze rozwiązanie do ograniczania użytkownika, aby wprowadzić liczbę w charakterze UITextFieldlub UITextVieww iOS swift

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool 
{
   return textField.text!.count < limit ? true : false
}

Uwaga: tutaj limit może być dowolny, od 1do nzgodnie z wymaganiami, na przykład: jeśli pracujesz na numerze telefonu, limitwartość będzie, 10 jeśli chcesz zastosować to samo, UITextViewtylko metoda zostanie zmieniona iw miejscu, w textfieldktórym będziesz używanytextview

Vipul Dungranee_MI
źródło