Limit character count in uitextview

I am giving a textual representation for a tweet of some line.

I use the following method to limit the number of characters to 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; } 

The code works well, except for the first condition that backspace does not work. Suppose I reach the limit of 140 characters so that the method gives me a lie and the user cannot insert more characters, but after that, when I try to delete some characters, the text view behaves as if it was disabled.

So, the question is how to remove characters from textview.text or re-enable text view.

+74
ios iphone uitextview uitextviewdelegate
Mar 22 '10 at 12:45
source share
15 answers

Instead, you should look for an empty string, as the link to the apple says

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

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

+62
Mar 22 '10 at 12:50
source share
 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { return textView.text.length + (text.length - range.length) <= 140; } 

This allows users to cut text or delete lines longer than one character (i.e., if they select and then press the Backspace key), or select a range and insert lines shorter or longer than it.

Swift Version 4.0

  func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { return textView.text.count + (text.count - range.length) <= 140 } 
+149
Nov 27 '10 at 0:26
source share

for quick 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 } 
+16
Dec 22 '17 at 7:28
source share

However, you can also use the below working code.

 - (void)textViewDidChange:(UITextView *)textView{ NSInteger restrictedLength=140; NSString *temp=textView.text; if([[textView text] length] > restrictedLength){ textView.text=[temp substringToIndex:[temp length]-1]; } } 
+10
Sep 05 2018-11-11T00:
source share

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 remove them if necessary

+5
Sep 05 2018-11-11T00:
source share

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
Dec 03 '14 at 8:22
source share

In Swift 5 and iOS 12, try the following implementation of the textView(_:shouldChangeTextIn:replacementText:) method textView(_:shouldChangeTextIn:replacementText:) which is part of the UITextViewDelegate protocol:

 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 } 
  • The most important part of this code is the conversion of range ( NSRange ) to rangeOfTextToReplace ( Range<String.Index> ). Check out this video tutorial to see why this conversion is important.
  • For this code to work correctly, you must also set the textField value smartInsertDeleteType to UITextSmartInsertDeleteType.no . This will prevent the possible insertion of (unwanted) extra space during the insert operation.



The full code example below shows how to implement textView(_:shouldChangeTextIn:replacementText:) in a 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 } } 
+3
Mar 19 '19 at 23:05
source share

Although I need an if-else , 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; } 

Inside the button is disabled. But if you want the user to not be able to post an empty test, just put a condition on the 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 } 
+2
Apr 12 '15 at 11:21
source share

The problem with some of the answers above: For example, I have a text box and I have to set a limit of 15 characters, and then stops after entering the 15th character. but they do not allow removal. That is, the delete button also does not work. Since I ran into the same problem. Went 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 have a text box whose tag I set to "6" and I limited max char limit = 30; works great in every case

+1
Mar 21 '14 at 14:38
source share

@Tim Gostony 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; } 
+1
Aug 24 '15 at 18:47
source share

Here we go for the best fit. Display the remaining number of characters: 'n' 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 } 
+1
Nov 16 '15 at 23:19
source share

Try the following: -

 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; } 
+1
Aug 16 '16 at 10:54 on
source share

If you also want to paste the code to the maximum number of characters, while reducing overflow and updating the counter 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 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 } } 
+1
Nov 08 '18 at 20:15
source share

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

 if ([textView.text length]>=3 && ![text isEqualToString:@""]) { return NO; } return YES; 
0
Jun 21 '14 at 16:14
source share
 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; } } 
0
Sep 12 '14 at 10:22
source share



All Articles