Set the maximum character length of a UITextField

IosObjective CCocoa TouchUitextfield

Ios Problem Overview


How can I set the maximum amount of characters in a UITextField on the iPhone SDK when I load up a UIView?

Ios Solutions


Solution 1 - Ios

While the UITextField class has no max length property, it's relatively simple to get this functionality by setting the text field's delegate and implementing the following delegate method:

Objective-C

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    // Prevent crashing undo bug – see note below.
    if(range.length + range.location > textField.text.length)
    {
        return NO;
    }
        
    NSUInteger newLength = [textField.text length] + [string length] - range.length;
    return newLength <= 25;
}

Swift

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
    let currentCharacterCount = textField.text?.count ?? 0
    if range.length + range.location > currentCharacterCount {
        return false
    }
    let newLength = currentCharacterCount + string.count - range.length
    return newLength <= 25
}

Before the text field changes, the UITextField asks the delegate if the specified text should be changed. The text field has not changed at this point, so we grab it's current length and the string length we're inserting (either through pasting copied text or typing a single character using the keyboard), minus the range length. If this value is too long (more than 25 characters in this example), return NO to prohibit the change.

When typing in a single character at the end of a text field, the range.location will be the current field's length, and range.length will be 0 because we're not replacing/deleting anything. Inserting into the middle of a text field just means a different range.location, and pasting multiple characters just means string has more than one character in it.

Deleting single characters or cutting multiple characters is specified by a range with a non-zero length, and an empty string. Replacement is just a range deletion with a non-empty string.

A note on the crashing "undo" bug

As is mentioned in the comments, there is a bug with UITextField that can lead to a crash.

If you paste in to the field, but the paste is prevented by your validation implementation, the paste operation is still recorded in the application's undo buffer. If you then fire an undo (by shaking the device and confirming an Undo), the UITextField will attempt to replace the string it thinks it pasted in to itself with an empty string. This will crash because it never actually pasted the string in to itself. It will try to replace a part of the string that doesn't exist.

Fortunately you can protect the UITextField from killing itself like this. You just need to ensure that the range it proposes to replace does exist within its current string. This is what the initial sanity check above does.

swift 3.0 with copy and paste working fine.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let str = (textView.text + text)
        if str.characters.count <= 10 {
            return true
        }
        textView.text = str.substring(to: str.index(str.startIndex, offsetBy: 10))
        return false
    }

Hope it's helpful to you.

Solution 2 - Ios

Swift 4

import UIKit

private var kAssociationKeyMaxLength: Int = 0

extension UITextField {
    
    @IBInspectable var maxLength: Int {
        get {
            if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLength) as? Int {
                return length
            } else {
                return Int.max
            }
        }
        set {
            objc_setAssociatedObject(self, &kAssociationKeyMaxLength, newValue, .OBJC_ASSOCIATION_RETAIN)
            addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
        }
    }
    
    @objc func checkMaxLength(textField: UITextField) {
        guard let prospectiveText = self.text,
            prospectiveText.count > maxLength
            else {
                return
        }
        
        let selection = selectedTextRange
        
        let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
        let substring = prospectiveText[..<indexEndOfText]
        text = String(substring)
        
        selectedTextRange = selection
    }
}

Edit: memory leak issue fixed.

enter image description here

Solution 3 - Ios

Thank you august! (Post)

This is the code that I ended up with which works:

#define MAX_LENGTH 20

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
	if (textField.text.length >= MAX_LENGTH && range.length == 0)
	{
		return NO; // return NO to not change text
	}
	else
	{return YES;}
}

Solution 4 - Ios

To complete August answer, an possible implementation of the proposed function (see UITextField's delegate).

I did not test domness code, but mine do not get stuck if the user reached the limit, and it is compatible with a new string that comes replace a smaller or equal one.

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    //limit the size :
    int limit = 20;
    return !([textField.text length]>limit && [string length] > range.length);
}

Solution 5 - Ios

You can't do this directly - UITextField has no maxLength attribute, but you can set the UITextField's delegate, then use:

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

Solution 6 - Ios

Often you have multiple input fields with a different length.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    int allowedLength;
    switch(textField.tag) {
        case 1: 
            allowedLength = MAXLENGTHNAME;      // triggered for input fields with tag = 1
            break;
        case 2:
            allowedLength = MAXLENGTHADDRESS;   // triggered for input fields with tag = 2
            break;
        default:
            allowedLength = MAXLENGTHDEFAULT;   // length default when no tag (=0) value =255
            break;
    }
        
    if (textField.text.length >= allowedLength && range.length == 0) {
        return NO; // Change not allowed
    } else {
        return YES; // Change allowed
    }
}

Solution 7 - Ios

The best way would be to set up a notification on the text changing. In your -awakeFromNib of your view controller method you'll want:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(limitTextField:) name:@"UITextFieldTextDidChangeNotification" object:myTextField];

Then in the same class add:

- (void)limitTextField:(NSNotification *)note {
    int limit = 20;
    if ([[myTextField stringValue] length] > limit) {
        [myTextField setStringValue:[[myTextField stringValue] substringToIndex:limit]];
    }
}

Then link up the outlet myTextField to your UITextField and it will not let you add any more characters after you hit the limit. Be sure to add this to your dealloc method:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UITextFieldTextDidChangeNotification" object:myTextField];

Solution 8 - Ios

This should be enough to solve the problem (replace 4 by the limit u want). Just make sure to add delegate in IB.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
     NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
     return (newString.length<=4);
}

Solution 9 - Ios

I created this UITextFieldLimit subclass:

  • Multiple textfields supported
  • Set the text length limit
  • Paste prevention
  • Displays a label of left characters inside the textfield, get hidden when you stop editing.
  • Shake animation when no characters left.

Grab the UITextFieldLimit.h and UITextFieldLimit.m from this GitHub repository:

https://github.com/JonathanGurebo/UITextFieldLimit

and begin to test!

Mark your storyboard-created UITextField and link it to my subclass using the Identity Inspector:

Identity Inspector

Then you can link it to an IBOutlet and set the limit(default is 10).


Your ViewController.h file should contain: (if you wan't to modify the setting, like the limit)

#import "UITextFieldLimit.h"

/.../

@property (weak, nonatomic) IBOutlet UITextFieldLimit *textFieldLimit; // <--Your IBOutlet

Your ViewController.m file should @synthesize textFieldLimit.


Set the text length limit in your ViewController.m file:

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

    [textFieldLimit setLimit:25];// <-- and you won't be able to put more than 25 characters in the TextField.
}

Hope the class helps you. Good luck!

Solution 10 - Ios

Use below extension to set the maximum character length of a UITextField and UITextView.

Swift 4.0

    private var kAssociationKeyMaxLength: Int = 0
    private var kAssociationKeyMaxLengthTextView: Int = 0
    extension UITextField {
        
        
        @IBInspectable var maxLength: Int {
            get {
                if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLength) as? Int {
                    return length
                } else {
                    return Int.max
                }
            }
            set {
                objc_setAssociatedObject(self, &kAssociationKeyMaxLength, newValue, .OBJC_ASSOCIATION_RETAIN)
                addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
            }
        }
        
        @objc func checkMaxLength(textField: UITextField) {
            guard let prospectiveText = self.text,
                prospectiveText.count > maxLength
                else {
                    return
            }
            
            let selection = selectedTextRange
            
            let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
            let substring = prospectiveText[..<indexEndOfText]
            text = String(substring)
            
            selectedTextRange = selection
        }
    }
    

#UITextView

extension UITextView:UITextViewDelegate {
        
        
        @IBInspectable var maxLength: Int {
            get {
                if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLengthTextView) as? Int {
                    return length
                } else {
                    return Int.max
                }
            }
            set {
                self.delegate = self
    
                objc_setAssociatedObject(self, &kAssociationKeyMaxLengthTextView, newValue, .OBJC_ASSOCIATION_RETAIN)
            }
        }
        
        public func textViewDidChange(_ textView: UITextView) {
            checkMaxLength(textField: self)
        }
        @objc func checkMaxLength(textField: UITextView) {
            guard let prospectiveText = self.text,
                prospectiveText.count > maxLength
                else {
                    return
            }
            
            let selection = selectedTextRange
            
            let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
            let substring = prospectiveText[..<indexEndOfText]
            text = String(substring)
            
            selectedTextRange = selection
        }
    }

You can set limit below.

enter image description here

Solution 11 - Ios

I simulate the actual string replacement that's about to happen to calculate that future string's length:

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

    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    
    if([newString length] > maxLength)
       return NO;

    return YES;
}

Solution 12 - Ios

There is generic solution for setting max length in Swift. By IBInspectable you can add new Attribute in Xcode Attribute Inspector.enter image description here

import UIKit
private var maxLengths = [UITextField: Int]()
extension UITextField {

    @IBInspectable var maxLength: Int {
        get {
            guard let length = maxLengths[self]
            else {
                return Int.max
            }
            return length
        }
        set {
            maxLengths[self] = newValue
            addTarget(
                self,
                action: Selector("limitLength:"),
                forControlEvents: UIControlEvents.EditingChanged
            )
        }
    }
    
    func limitLength(textField: UITextField) {
        guard let prospectiveText = textField.text
            where prospectiveText.characters.count > maxLength else {
                return
        }
        let selection = selectedTextRange
        text = prospectiveText.substringWithRange(
            Range<String.Index>(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength))
        )
        selectedTextRange = selection
    }
    
}

Solution 13 - Ios

Swift 3 version //***** This will NOT work with Swift 2.x! *****//

First create a new Swift file : TextFieldMaxLength.swift, and then add the code below:

import UIKit

private var maxLengths = [UITextField: Int]()

extension UITextField {

   @IBInspectable var maxLength: Int {

      get {
  
          guard let length = maxLengths[self] 
             else {
                return Int.max
      }
      return length
   }
   set {
      maxLengths[self] = newValue
      addTarget(
         self,
         action: #selector(limitLength),
         for: UIControlEvents.editingChanged
      )
   }
}
func limitLength(textField: UITextField) {
    guard let prospectiveText = textField.text,
        prospectiveText.characters.count > maxLength
    else {
        return
    }

   let selection = selectedTextRange
   let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
   text = prospectiveText.substring(to: maxCharIndex)
   selectedTextRange = selection
   }
}

and then you will see in Storyboard a new field (Max Length) when you select any TextField

if you still have more questions check out this link: http://www.globalnerdy.com/2016/05/18/ios-programming-trick-how-to-use-xcode-to-set-a-text-fields-maximum-length-visual-studio-style/

Solution 14 - Ios

Using Interface builder you can link and get the event for "Editing changed" in any of your function. Now there you can put check for the length

- (IBAction)onValueChange:(id)sender 
{
	NSString *text = nil;
    int MAX_LENGTH = 20;
	switch ([sender tag] ) 
    {
		case 1: 
		{
			text = myEditField.text;
			if (MAX_LENGTH < [text length]) {
				myEditField.text = [text substringToIndex:MAX_LENGTH];
			}
		}
			break;
		default:
			break;
	}
	
}

Solution 15 - Ios

The following code is similar to sickp's answer but handles correctly copy-paste operations. If you try to paste a text that is longer than the limit, the following code will truncate the text to fit the limit instead of refusing the paste operation completely.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    static const NSUInteger limit = 70; // we limit to 70 characters
    NSUInteger allowedLength = limit - [textField.text length] + range.length;
    if (string.length > allowedLength) {
        if (string.length > 1) {
            // get at least the part of the new string that fits
            NSString *limitedString = [string substringToIndex:allowedLength];
            NSMutableString *newString = [textField.text mutableCopy];
            [newString replaceCharactersInRange:range withString:limitedString];
            textField.text = newString;
        }
        return NO;
    } else {
        return YES;
    }
}

Solution 16 - Ios

To make it work with cut & paste of strings of any length, I would suggest changing the function to something like:

#define MAX_LENGTH 20

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    {
        NSInteger insertDelta = string.length - range.length;
    
        if (textField.text.length + insertDelta > MAX_LENGTH)
        {
           return NO; // the new string would be longer than MAX_LENGTH
        }
        else {
            return YES;
        }
    }

Solution 17 - Ios

Swift 4

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let text = textField.text else { return true }
    let newLength = text.count + string.count - range.length
    return newLength <= 10
}

Solution 18 - Ios

Swift 2.0 +

First of all create a class for this process. Lets call it StringValidator.swift.

Then just paste the following code inside it.

import Foundation

extension String {

func containsCharactersIn(matchCharacters: String) -> Bool {
let characterSet = NSCharacterSet(charactersInString: matchCharacters)
return self.rangeOfCharacterFromSet(characterSet) != nil
}

func containsOnlyCharactersIn(matchCharacters: String) -> Bool {
let disallowedCharacterSet = NSCharacterSet(charactersInString: matchCharacters).invertedSet
return self.rangeOfCharacterFromSet(disallowedCharacterSet) == nil
}


func doesNotContainCharactersIn(matchCharacters: String) -> Bool {
let characterSet = NSCharacterSet(charactersInString: matchCharacters)
return self.rangeOfCharacterFromSet(characterSet) == nil
}

func isNumeric() -> Bool
{
let scanner = NSScanner(string: self)
scanner.locale = NSLocale.currentLocale()

return scanner.scanDecimal(nil) && scanner.atEnd
}

}

Now save the class.....

Usage..

Now goto your viewController.swift class and make your textfield's outlets as..

@IBOutlet weak var contactEntryTxtFld: UITextField! //First textfield
@IBOutlet weak var contactEntryTxtFld2: UITextField!   //Second textfield

Now goto the textfield's shouldChangeCharactersInRange method and use like the following.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if string.characters.count == 0 {
        return true
    }
    let latestText = textField.text ?? ""
    let checkAbleText = (latestText as NSString).stringByReplacingCharactersInRange(range, withString: string)
    
    
    switch textField {
        
    case contactEntryTxtFld:
        return checkAbleText.containsOnlyCharactersIn("0123456789") && prospectiveText.characters.count <= 5
        
    case contactEntryTxtFld2:
        return checkAbleText.containsOnlyCharactersIn("0123456789") && prospectiveText.characters.count <= 5
        
    default:
        return true
    }

}

Don't forget to set the delegate protocol/methods of textfields.

Let me explain about this... I am using the simple extension process of string which I wrote inside an another class. Now I am just calling those extension methods from another class where I need them by adding check and maximum value.

Features...

  1. It will set maximum limit of a particular textfield.
  2. It will set type of accepted keys for particular textfield.

Types...

containsOnlyCharactersIn //Accepts only Characters.

containsCharactersIn //Accepts combination of characters

doesNotContainsCharactersIn //Will not accept characters

Hope this helped.... Thanks..

Solution 19 - Ios

swift 3.0

This code is working fine when you are paste string more than your character limits.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let str = (textView.text + text)
        if str.characters.count <= 10 {
            return true
        }
        textView.text = str.substring(to: str.index(str.startIndex, offsetBy: 10))
        return false
    }

Thanks for your votes. :)

Solution 20 - Ios

I give a supplementary answer based on @Frouo. I think his answer is the most beautiful way. Becuase it's a common control we can reuse.

private var kAssociationKeyMaxLength: Int = 0

extension UITextField {
    
    @IBInspectable var maxLength: Int {
        get {
            if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLength) as? Int {
                return length
            } else {
                return Int.max
            }
        }
        set {
            objc_setAssociatedObject(self, &kAssociationKeyMaxLength, newValue, .OBJC_ASSOCIATION_RETAIN)
            self.addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
        }
    }
    
    func checkMaxLength(textField: UITextField) {
        
        guard !self.isInputMethod(), let prospectiveText = self.text,
            prospectiveText.count > maxLength
            else {
                return
        }
        
        let selection = selectedTextRange
        let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
        text = prospectiveText.substring(to: maxCharIndex)
        selectedTextRange = selection
    }
    
    //The method is used to cancel the check when use Chinese Pinyin input method.
    //Becuase the alphabet also appears in the textfield when inputting, we should cancel the check.
    func isInputMethod() -> Bool {
        if let positionRange = self.markedTextRange {
            if let _ = self.position(from: positionRange.start, offset: 0) {
                return true
            }
        }
        return false
    }
    
}

Solution 21 - Ios

This is the correct way to handle max length on UITextField, it allows the return key to exit the resign the textfield as first responder and lets the user backspace when they reach the limit

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
int MAX_LENGHT = 5;
    if([string isEqualToString:@"\n"])
    {
        [textField resignFirstResponder];
        return FALSE;
    }
    else if(textField.text.length > MAX_LENGHT-1)
    {
        if([string isEqualToString:@""] && range.length == 1)
        {
            return TRUE;
        }
        else
        {
            return FALSE;
        }
    }
    else
    {
        return TRUE;
    }
}

Solution 22 - Ios

What about this simple approach. Its working fine for me.

extension UITextField {

    func  charactersLimit(to:Int) {
    
        if (self.text!.count > to) {
            self.deleteBackward()
        }
    }
}

Then:

someTextField.charactersLimit(to:16)

Solution 23 - Ios

Other answers do not handle the case where user can paste a long string from clipboard. If I paste a long string it should just be truncated but shown. Use this in your delegate:

static const NSUInteger maxNoOfCharacters = 5;

-(IBAction)textdidChange:(UITextField * )textField
{
NSString * text = textField.text;

if(text.length > maxNoOfCharacters)
{
    text = [text substringWithRange:NSMakeRange(0, maxNoOfCharacters)];
    textField.text = text;
}

// use 'text'

}

Solution 24 - Ios

now how many characters u want just give values

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range   replacementString:(NSString *)string {
     NSUInteger newLength = [textField.text length] + [string length] - range.length;
     return (newLength > 25) ? NO : YES;
  }

Solution 25 - Ios

Got it down to 1 line of code :)

Set your text view's delegate to "self" then add the <UITextViewDelegate> in your .h and the following code in your .m .... you can adjust the number "7" to be whatever you want your MAXIMUM number of characters to be.

-(BOOL)textView:(UITextView *)a shouldChangeTextInRange:(NSRange)b replacementText:(NSString *)c {
    return ((a.text.length+c.length<=7)+(c.length<1)+(b.length>=c.length)>0);
}

This code accounts for typing new characters, deleting characters, selecting characters then typing or deleting, selecting characters and cutting, pasting in general, and selecting characters and pasting.

Done!






Alternatively, another cool way to write this code with bit-operations would be

-(BOOL)textView:(UITextView *)a shouldChangeTextInRange:(NSRange)b replacementText:(NSString *)c {
    return 0^((a.text.length+c.length<=7)+(c.length<1)+(b.length>=c.length));
}

Solution 26 - Ios

I have implemented a UITextField Extension to add a maxLength property to it.

It's based on Xcode 6 IBInspectables, so you can set the maxLength limit on the Interface builder.

Here is the implementation:

> UITextField+MaxLength.h

#import <UIKit/UIKit.h>

@interface UITextField_MaxLength : UITextField<UITextFieldDelegate>

@property (nonatomic)IBInspectable int textMaxLength;
@end

> UITextField+MaxLength.m

#import "UITextField+MaxLength.h"

@interface UITextField_MaxLength()

@property (nonatomic, assign) id <UITextFieldDelegate> superDelegate;

@end

@implementation UITextField_MaxLength

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

    //validate the length, only if it's set to a non zero value
    if (self.textMaxLength>0) {
        if(range.length + range.location > textField.text.length)
            return NO;
        
        if (textField.text.length+string.length - range.length>self.textMaxLength) {
            return NO;
        }
    }
    
    //if length validation was passed, query the super class to see if the delegate method is implemented there
    if (self.superDelegate && [self.superDelegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) {
        return [self.superDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string];
    }
    else{
        //if the super class does not implement the delegate method, simply return YES as the length validation was passed
        return YES;
    }
}

- (void)setDelegate:(id<UITextFieldDelegate>)delegate {
    if (delegate == self)
        return;
    self.superDelegate = delegate;
    [super setDelegate:self];
}

//forward all non overriden delegate methods
- (id)forwardingTargetForSelector:(SEL)aSelector {
    if ([self.superDelegate  respondsToSelector:aSelector])
        return self.superDelegate;
    
    return [super forwardingTargetForSelector:aSelector];
}

- (BOOL)respondsToSelector:(SEL)aSelector {
    if ([self.superDelegate respondsToSelector:aSelector])
        return YES;
    
    return [super respondsToSelector:aSelector];
}
@end

Solution 27 - Ios

I have open sourced a UITextField subclass, STATextField, that offers this functionality (and much more) with its maxCharacterLength property.

Solution 28 - Ios

Use this code here RESTRICTED_LENGTH is length you want to restrict for textfield.

   - (BOOL)textField:(UITextField *)textField     shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (textField == nameTF) {
    int limit = RESTRICTED_LENGTH - 1;
    return !([textField.text length]>limit && [string length] > range.length);
    }
   else
   {
    return YES;
   }

return NO;

}

Solution 29 - Ios

I did this in Swift for an 8 character limit when using a number pad.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    return !(textField.text?.characters.count == MAX_LENGTH && string != "")
}

I had to test for string != "" to allow the delete button to work on the number pad, otherwise it wouldn't allow deleting characters in the text field after it reached its max.

Solution 30 - Ios

For Xamarin:

YourTextField.ShouldChangeCharacters = 
delegate(UITextField textField, NSRange range, string replacementString)
        {
            return (range.Location + replacementString.Length) <= 4; // MaxLength == 4
        };

Solution 31 - Ios

If your purpose of limiting text count is to ensure that text will fit into a UILabel elsewhere, I'd avoid using character count. It breaks down with some emoji (trying to truncate a double size emoji will likely crash your app). It's also an issue with some languages like Japanese and Chinese, which have a two-step input process where a simple count just won't work.

I built out a UITextField drop-in subclass (MPC_CharacterLimitedTextField on github). You feed it the expected output label width and it will handle all languages, emoji, and pasting issues. It will harvest only as many full characters that will fit into the label, regardless of the character count. There's a demo in the project so you can test it to see if it's what you need. Hope it will help anybody who was having the same problems with output length that I was.

Solution 32 - Ios

You can also do this using NotificationCenter in Swift 4

NotificationCenter.default.addObserver(self, selector: #selector(self.handleTextChange(recognizer:)), name: NSNotification.Name.UITextFieldTextDidChange, object: yourTextField)
    
    @objc func handleTextChange(recognizer: NSNotification) {
            //max length is 50 charater max
            let textField = recognizer.object as! UITextField
            
            if((textField.text?.count)! > 50) {
                let newString: String? = (textField.text as NSString?)?.substring(to: 50)
                textField.text = newString
                
            }         
        }

Solution 33 - Ios

Swift 4.2 and UITextFieldDelegate method

This works for me and limits the textfield to have a max input of 8 characters. Hopefully NSRange will eventually be changed to Range but for now I am happy to use NSString as creating a Range from NSRange involves dealing with another optional.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let text = textField.text ?? ""
    let nsString = text as NSString
    let newText = nsString.replacingCharacters(in: range, with: string)
    return newText.count <= 8
}

Solution 34 - Ios

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

Solution 35 - Ios

(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
	NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];

	if ([txt_name.text length]>100)
	{
		return NO;
	}
	
    return YES;
}

Solution 36 - Ios

we can set the range of textfield like this..

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range  replacementString:(NSString *)string
{
     int setrange = 20;
     return !([textField.text length]>setrange && [string length] > range.length);
}

Solution 37 - Ios

This limits the number of characters, but also make sure that you can paste in the field until the maximum limit.

- (void)textViewDidChange:(UITextView *)textView
{
    NSString* str = [textView text];
    str = [str substringToIndex:MIN(1000,[str length])];
    [textView setText:str];
    
    if([str length]==1000) {
        // show some label that you've reached the limit of 1000 characters
    }
}

Solution 38 - Ios

Slightly beyond answering the original question, and expanding on Frouo's answer, here are extensions to trim a String of whitespace and to a max length, and to utilize those String extensions to trim a UITextField to a max length:

// In String_Extensions.swift

extension String {
  
  func trimmedString() -> String {
    var trimmedString = self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
    let components = trimmedString.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).filter { count($0) > 0 }
    return " ".join(components)
  }
  
  func trimmedStringToMaxLength(maxLength: Int) -> String {
    return trimmedString().substringToIndex(advance(startIndex, min(count(self), maxLength))).trimmedString()
  }
  
}

// In UITextField_Extensions.swift

private var maxLengthDictionary = [UITextField : Int]()
private var textFieldMaxLength = 20

extension UITextField {
  
  @IBInspectable var maxLength: Int {
    get {
      if let maxLength = maxLengthDictionary[self] {
        return maxLength
      } else {
        return textFieldMaxLength
      }
    }
    set {
      maxLengthDictionary[self] = newValue < textFieldMaxLength + 1 ? newValue : textFieldMaxLength
    }
  }
  
  func trimAndLimitToMaxLength() {
    text = text.trimmedStringToMaxLength(maxLength)
  }
  
}

let someTextField = UITextField()
let someString = "   This   is   a   string   that   is longer than allowable for a text field.   "
someTextField.text = someString
someTextField.trimAndLimitToMaxLength()
println(someTextField.text) // Prints "This is a string tha"
let anotherTextField = UITextField()
anotherTextField.maxLength = 5
anotherTextField.text = someString
anotherTextField.trimAndLimitToMaxLength()
println(anotherTextField.text) // Prints "This"

trimAndLimitToMaxLength() could be used in UITextFieldDelegate's textFieldDidEndEditing(_:) so that a user could enter or paste in a longer than acceptable string and then shorten it vs. just cutting off the input at the max length. In doing this, I would also set attributed text styles to indicate any portion of the text that goes beyond the acceptable length (e.g., [NSBackgroundColorAttributeName : UIColor.redColor(), NSForegroundColorAttributeName : UIColor.whiteColor(), NSStrikethroughStyleAttributeName : NSNumber(int: 1)]

Solution 39 - Ios

For Swift 2.1+

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    
    if (range.length + range.location > textField.text!.characters.count )
    {
        return false;
    }
    
    let newLength = textField.text!.characters.count + string.characters.count - range.length
    return newLength <= 25
}

Hope it helps

Solution 40 - Ios

I want to add to the answer given by @sickp.

There is an issue in his Swift code that occurs with any multibyte text (e.g. emojis). NSRange and String in Swift are not compatible, so it's frustrating that the delegate class combines them. The trick is simply to convert the String objects to NSString The correct solution, based on what @sickp wrote, is actually this:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

	let currentText = (textField.text as NSString?) ?? NSString()
	let currentCharacterCount = currentText.length
	if range.length + range.location > currentCharacterCount {
		return false
	}
	let newLength = currentText.replacingCharacters(in: range, with: string).characters.count
	return newLength <= 25
}

Solution 41 - Ios

for Swift 3.1 or later

firstly add protocol UITextFieldDelegate

like:-

class PinCodeViewController: UIViewController, UITextFieldDelegate { 
.....
.....
.....

}

after that create your UITextField and set delegate

Complete Exp: -

import UIKit
            
class PinCodeViewController: UIViewController, UITextFieldDelegate {
                
let pinCodetextField: UITextField = {
    let tf = UITextField()
    tf.placeholder = "please enter your pincode"
    tf.font = UIFont.systemFont(ofSize: 15)
    tf.borderStyle = UITextBorderStyle.roundedRect
    tf.autocorrectionType = UITextAutocorrectionType.no
    tf.keyboardType = UIKeyboardType.numberPad
    tf.clearButtonMode = UITextFieldViewMode.whileEditing;
    tf.contentVerticalAlignment = UIControlContentVerticalAlignment.center
 return tf
  }()
                
            
 override func viewDidLoad() {
   super.viewDidLoad()
   view.addSubview(pinCodetextField)
    //----- setup your textfield anchor or position where you want to show it----- 
    
    
    // after that 
pinCodetextField.delegate = self // setting the delegate
                   
 }
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    return !(textField.text?.characters.count == 6 && string != "")
     } // this is return the maximum characters in textfield 
    }

Solution 42 - Ios

Working in Swift 5.2:

 class AngListVC: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var angTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        angTextField.delegate = self
        angTextField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
      
    }

   func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
           let userText =  angTextField.text ?? ""
           var newText = ""
           if range.length > 0 {
               let txt = NSString(string: userText)
               if txt.length > 0 {
                   newText = txt.replacingCharacters(in: range, with: "")
               }
           } else {
               newText = userText + ""
           }
           return newText.count <= 3
       }

@objc func textFieldDidChange(_ textField: UITextField) {
        print("textFieldDidChange")
   }

Solution 43 - Ios

For Swift 5

Add this extension of UITextfield and then select a textfield and check attribute inspector

private var __maxLengths = [UITextField: Int]()

extension UITextField {
    @IBInspectable var maxLength: Int {
        get {
            guard let l = __maxLengths[self] else {
               return 150 // (default int limit)
            }
            return l
        }
        set {
            __maxLengths[self] = newValue
            addTarget(self, action: #selector(setMaxLength), for: .editingChanged)
        }
    }

    @objc func setMaxLength(textField: UITextField) {
        let t = textField.text
        textField.text = t?.prefix(maxLength).description
    }
}

enter image description here

Solution 44 - Ios

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField.text.length >= 50) {
        return NO;
    }
    return YES;
}

Solution 45 - Ios

Swift 4.2+

By implementing UITextFieldDelegate method

  1. ViewController:

     class MyViewController: UIViewController {
    
         let MAX_LENGTH = 256
         
         @IBOutlet weak var myTextField: UITextField!
     
         override viewDidLoad() {
             self.myTextField.delegate = self
         }
     }
    
  2. Delegate:

     extension MyViewController: UITextFieldDelegate {
    
         func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
             let userText =  textView.text ?? ""
             var newText = ""
             if range.length > 0 {
                 let txt = NSString(string: userText)
                 if txt.length > 0 {
                     newText = txt.replacingCharacters(in: range, with: text)
                 }
             } else {
                 newText = userText + text
             }
             return newText.count <= MAX_LENGTH
         }
     
     }
    

Solution 46 - Ios

I found this quick and simple

- (IBAction)backgroundClick:(id)sender {
    if (mytext.length <= 7) {
        [mytext resignFirstResponder];
    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Too Big" 
                                                        message:@"Please Shorten Name"
                                                       delegate:nil 
                                              cancelButtonTitle:@"Cancel"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
}
 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDomnessView Question on Stackoverflow
Solution 1 - IosTrashpandaView Answer on Stackoverflow
Solution 2 - IosfrouoView Answer on Stackoverflow
Solution 3 - IosDomnessView Answer on Stackoverflow
Solution 4 - IosJminiView Answer on Stackoverflow
Solution 5 - IosAugustView Answer on Stackoverflow
Solution 6 - IosVincentView Answer on Stackoverflow
Solution 7 - IosMartin PilkingtonView Answer on Stackoverflow
Solution 8 - IosNishantView Answer on Stackoverflow
Solution 9 - IosJonathan GureboView Answer on Stackoverflow
Solution 10 - IosHitesh SuraniView Answer on Stackoverflow
Solution 11 - IossamvermetteView Answer on Stackoverflow
Solution 12 - IosHirenView Answer on Stackoverflow
Solution 13 - IosGilad BrunfmanView Answer on Stackoverflow
Solution 14 - IosVishal KumarView Answer on Stackoverflow
Solution 15 - IoswrolukView Answer on Stackoverflow
Solution 16 - IosPåhl MelinView Answer on Stackoverflow
Solution 17 - IosShan YeView Answer on Stackoverflow
Solution 18 - IosonCompletionView Answer on Stackoverflow
Solution 19 - IosIlesh PView Answer on Stackoverflow
Solution 20 - IosVictor ChoyView Answer on Stackoverflow
Solution 21 - IosandersView Answer on Stackoverflow
Solution 22 - IosJoaquin PereiraView Answer on Stackoverflow
Solution 23 - Ios8suhasView Answer on Stackoverflow
Solution 24 - Iosmahesh chowdaryView Answer on Stackoverflow
Solution 25 - IosAlbert RenshawView Answer on Stackoverflow
Solution 26 - IosLefterisView Answer on Stackoverflow
Solution 27 - IosStunnerView Answer on Stackoverflow
Solution 28 - IosAmit ShelgaonkarView Answer on Stackoverflow
Solution 29 - Iosu84sixView Answer on Stackoverflow
Solution 30 - IosKeduView Answer on Stackoverflow
Solution 31 - IosMike CritchleyView Answer on Stackoverflow
Solution 32 - IosPramod MoreView Answer on Stackoverflow
Solution 33 - IosEdwardView Answer on Stackoverflow
Solution 34 - IosJasmeetView Answer on Stackoverflow
Solution 35 - IosMubin ShaikhView Answer on Stackoverflow
Solution 36 - IosRudraView Answer on Stackoverflow
Solution 37 - IosjacklehamsterView Answer on Stackoverflow
Solution 38 - IosScott GardnerView Answer on Stackoverflow
Solution 39 - IosChris KlinglerView Answer on Stackoverflow
Solution 40 - IosGuy KogusView Answer on Stackoverflow
Solution 41 - IosNandkishor mewaraView Answer on Stackoverflow
Solution 42 - IosClean CoderView Answer on Stackoverflow
Solution 43 - IosAbdul Karim KhanView Answer on Stackoverflow
Solution 44 - IosGaurav GilaniView Answer on Stackoverflow
Solution 45 - IosPocheshireView Answer on Stackoverflow
Solution 46 - IosPaul CutlerView Answer on Stackoverflow