Limit number of characters in uitextview

2019-01-16 03:50发布

问题:

I am giving a text view to tweet some string .

I am applying the following method to restrict the number of characters to 140 in length.

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

The code is working nicely except the first condition that backspace is not working. suppose that I have reached the limit of 140 characters so that the method will give me false and the user can not insert more characters but after that when I try to delete some characters the text view behave as it is disabled .

So the question how do delete characters from textview.text or re-enable the text view .

回答1:

You should be looking for an empty string instead, as the apple reference says

If the user presses the Delete key, the length of the range is 1 and an empty string object replaces that single character.

I think the check you actually want to make is something like [[textView text] length] - range.length + text.length > 140, to account for cut/paste operations.



回答2:

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

This accounts for users cutting text, or deleting strings longer than a single character (ie if they select and then hit backspace), or highlighting a range and pasting strings shorter or longer than it.

Swift 2.0 Version

 func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    return textView.text.characters.count + (text.characters.count - range.length) <= 140
}


回答3:

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


回答4:

However you can use below working code also..

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

    NSInteger restrictedLength=140;

    NSString *temp=textView.text;

    if([[textView text] length] > restrictedLength){
        textView.text=[temp substringToIndex:[temp length]-1];
    }
}


回答5:

ue this

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

    int limit = 139;

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

}

this will only enter 140 char and you can delete them if need



回答6:

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


回答7:

Though I needed an if-else condition, so this worked for me:

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

Intially the button is set to disabled. But if you want user cant post an empty test, simply put a condition on button click:

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


回答8:

The Problem with some of the answer given above is, For example I have a text field and I have to set a limit of 15 characters input, then it stops after entering 15th Character. but they Don't allow to delete. That is the delete button also don't work. As I was facing the same problem. Came out with the solution , Given Below. Works Perfect for Me

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

I am having a text field, whose tag I have set "6" and I have restricted the max char limit = 30 ; works fine in every case



回答9:

@Tim Gostony 's Swift Version:

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


回答10:

Here we go for best fit. Display number of characters left: 'n' characters left.

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
}


回答11:

Try this out:-

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


回答12:

Write below code in textView:shouldChangeTextInRange:replacementText: method :

if ([textView.text length]>=3 && ![text isEqualToString:@""]) {
    return NO;
}
return YES;


回答13:

Use the following code...
- (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;
    }
}


回答14:

If you're also looking to be able to paste code up to the max character count, while cutting off overflow, and updating a count label:

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
}

With the extension:

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