Ограничить количество символов в uitextview

80

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

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

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

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

Возникает вопрос: «Как удалить символы из textview.textтекстового представления или снова включить его?»

харшальб
источник
Отметьте этот ответ
Hemang

Ответы:

67

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

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

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

Дэвид Гелхар
источник
спасибо, но могу быть более конкретным, я не могу понять техническую спецификацию яблока
harshalb
просто скажите мне, что я должен поставить в первое условие. Я голодаю за это почти 4 часа
harshalb
9
Я думаю, что проверка, которую вы действительно хотите сделать, - это что-то вроде [[textView text] length] - range.length + text.length > 140учета операций вырезания / вставки.
Дэвид Гелхар
2
[[textView text] length] - range.length + text.length> 140 должно быть [[textView text] length] - range.length + text.length <140
Kuzon
Kuzon, нет, если вы возвращаете true по умолчанию и хотите вернуть false, если вы превысите ограничение в 140 символов.
камень
165
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    return textView.text.length + (text.length - range.length) <= 140;
}

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

Версия Swift 4.0

 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    return textView.text.count + (text.count - range.length) <= 140
}
Тим
источник
это IBAction? как мне подключить его к рассматриваемому TextView в качестве типов пользователей?
учащийся
1
Надо сделать ваш контроллер представления UITextViewDelegate, а затем подключить владельца файла в качестве делегата текстового представления
Тим,
Я подумал, что было бы справедливее задать следующий вопрос: у меня проблемы с наличием двух UITextviews, которым нужны ограничения на количество символов в одном контроллере. Не могли бы вы помочь? stackoverflow.com/questions/25272413/…
учащийся
Это должно быть отмечено как правильный ответ. Спасибо
Эрнан Арбер
Это вызовет сбой, если вы вставите слишком длинный текст (поэтому falseбудет возвращен), а затем вы попытаетесь отменить действие.
Раймундас Сакалаускас
18

для быстрого 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

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

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

    NSInteger restrictedLength=140;

    NSString *temp=textView.text;

    if([[textView text] length] > restrictedLength){
        textView.text=[temp substringToIndex:[temp length]-1];
    }
}
Сародж
источник
Обычно это не лучший способ редактировать что-либо после того, как это было установлено. Лучше проверить это в "shouldChangeCharactersInRange", чтобы текст не редактировался.
Benjamin Piette
7

В 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«S 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
    }

}
Иману Пети
источник
5

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;
}
Александр Волков
источник
countElementsбыл заменен на countSwift 1.2
Тим Виндзор Браун
1
а в Swift 2 вам нужно использовать textView.text.characters.count или любую другую кодировку, которую вы хотите: developer.apple.com/swift/blog/?id=30
Heckscheibe
4

уэ это

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

    int limit = 139;

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

}

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

B25Dec
источник
4

Ограничьте переполнение, а не весь текст!

По возвращению falseв ...shouldChangeTextInRange...методе делегата, вы на самом деле ограничиваете весь текст и обработки следующих ситуаций могут быть так трудно:

  • Копирование и вставка
  • Выберите область текста и отредактируйте
  • Использование автоматического предложения
  • Использование голосового ввода (голосовая команда или диктовка)

Так что вы можете:

Просто ограничьте переполнение текста

Удалив лишние символы:

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

Вы можете сделать это даже на лету ! поместив этот код в действие объекта textViewили textFieldс .editingChangedсобытием.

Моджтаба Хоссейни
источник
Размещение этого в делегате UITextView func textViewDidChange(_ textView: UITextView) {...}прекрасно работает, только обрезая конец длинного вставленного текста
Жосселин
2

Хотя мне нужно было 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

Проблема с некоторыми из приведенных выше ответов: например, у меня есть текстовое поле, и я должен установить ограничение в 15 символов ввода, затем он останавливается после ввода 15-го символа. но они не позволяют удалить. То есть кнопка удаления тоже не работает. Поскольку я столкнулся с той же проблемой. Вышел с решением, данным ниже. Идеально подходит для меня

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

У меня есть текстовое поле, тег которого я установил "6", и я ограничил max char limit = 30; отлично работает в любом случае

Jasmeet
источник
1

Быстрая версия @Tim Gostony:

// 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;
}
Майкл Шанг
источник
1

Вот и все, что вам нужно. Отобразить количество оставшихся символов: осталось n символов.

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
}
Вентилятор YSR
источник
1

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

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

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

 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
}
Абхиджит Маллик
источник
0

Напишите ниже код в textView:shouldChangeTextInRange:replacementText:методе:

if ([textView.text length]>=3 && ![text isEqualToString:@""]) {
    return NO;
}
return YES;
user2493047
источник
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
источник
0

Используйте следующий код.

- (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;
    }
}
Викас Гранди
источник
если для удаления символов из текстового представления используется
условие
0

Вот простейшее решение для ограничения пользователя вводить количество символов UITextFieldв UITextViewiOS swift или в него.

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

Примечание: здесь ограничение может быть любым от 1до nв соответствии с вашим требованием, например: если вы работаете с номером телефона, limitзначение будет, 10 если вы хотите применить то же самое, UITextViewтолько метод будет изменен, и в том месте, где textfieldвы будете использоватьtextview

Випул Дунгранее_МИ
источник