Ограничить количество символов в uitextview - PullRequest
72 голосов
/ 22 марта 2010

Я даю текстовое представление, чтобы чирикать какую-то строку.

Я применяю следующий метод, чтобы ограничить количество символов длиной до 140.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{


    if([text isEqualToString:@"\b"]){
        DLog(@"Ohoooo");
        return YES;
    }else if([[textView text] length] > 140){

        return NO;
    }

    return YES;
}

Код работает хорошо, за исключением первого условия, что Backspace не работает. Предположим, что я достиг предела в 140 символов, так что метод выдаст мне false, и пользователь не сможет вставить больше символов, но после этого, когда я пытаюсь удалить некоторые символы, текстовое представление ведет себя как отключенное.

Так что вопрос, как удалить символы из textview.text или повторно включить текстовое представление.

Ответы [ 15 ]

146 голосов
/ 27 ноября 2010
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    return textView.text.length + (text.length - range.length) <= 140;
}

Это позволяет пользователям вырезать текст или удалять строки длиннее одного символа (т. Е. Если они выбирают и затем нажимают клавишу Backspace), либо выделять диапазон и вставлять строки короче или длиннее его.

Версия Swift 4.0

 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    return textView.text.count + (text.count - range.length) <= 140
}
61 голосов
/ 22 марта 2010

Вместо этого вы должны искать пустую строку, так как ссылка apple говорит

Если пользователь нажимает клавишу Delete, длина диапазона равна 1, и пустой символ строки заменяет этот единственный символ.

Я думаю, что чек, который вы на самом деле хотите сделать, это что-то вроде [[textView text] length] - range.length + text.length > 140 для учета операций вырезания / вставки.

15 голосов
/ 22 декабря 2017

для быстрой 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
}
10 голосов
/ 05 сентября 2011

Однако вы можете использовать ниже рабочий код также ..

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

    NSInteger restrictedLength=140;

    NSString *temp=textView.text;

    if([[textView text] length] > restrictedLength){
        textView.text=[temp substringToIndex:[temp length]-1];
    }
}
5 голосов
/ 03 декабря 2014

Swift:

// 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;
}
5 голосов
/ 05 сентября 2011

эээ

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

    int limit = 139;

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

}

это будет ввести только 140 символов, и вы можете удалить их, если нужно

2 голосов
/ 20 марта 2019

В Swift 5 и iOS 12 попробуйте следующую реализацию метода textView(_:shouldChangeTextIn:replacementText:), который является частью протокола UITextViewDelegate:

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
}
  • Наиболее важной частью этого кода является преобразование из range (NSRange) в rangeOfTextToReplace (Range<String.Index>). Посмотрите этот видеоурок , чтобы понять, почему это преобразование важно.
  • Чтобы этот код работал правильно, вам также следует установить значение textField smartInsertDeleteType на UITextSmartInsertDeleteType.no. Это предотвратит возможную вставку (нежелательного) дополнительного пространства при выполнении операции вставки.

Полный пример кода ниже показывает, как реализовать textView(_:shouldChangeTextIn:replacementText:) в 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
    }

}
2 голосов
/ 12 апреля 2015

Хотя мне нужно было условие if-else, у меня это сработало:

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

По сути, кнопка отключена.Но если вы хотите, чтобы пользователь не мог опубликовать пустой тест, просто поставьте условие на нажатие кнопки:

- (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
}
1 голос
/ 08 ноября 2018

Если вы также хотите вставить код до максимального количества символов, одновременно сократив переполнение и обновив метку счетчика:

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
}

С расширением:

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
    }
}
1 голос
/ 16 августа 2016

Попробуйте: -

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

    if(textView.text.characters.count > 20 && range.length == 0) {
        print("Please summarize in 20 characters or less")
        return false;
    }

    return true;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...