Set the maximum character length of a UITextField in Swift
Asked Answered
M

23

126

I know there are other topics on this, but I can't seem to find out how to implement it.

I'm trying to limit a UITextField to only five characters.

Preferably alphanumeric, -, ., and _.

I've seen this code:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange,
                       replacementString string: String) -> Bool
{
    let maxLength = 4
    let currentString: NSString = textField.text
    let newString: NSString =
             currentString.stringByReplacingCharactersInRange(range, withString: string)
    return newString.length <= maxLength
}

and

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

    let length = count(textField.text.utf16) + count(string.utf16) - range.length
    return length <= 10
}

How can I actually implement it? Which "textfield" should I swap out for my custom named UITextField?

Memphian answered 12/7, 2015 at 0:32 Comment(2)
Swift 4 implementation https://mcmap.net/q/75588/-uitextfield-setting-maximum-character-length-in-swiftArthrospore
Quick alert - to shorten a String in Swift these days you can finally just .prefix(n)Addendum
I
193
  1. Your view controller should conform to UITextFieldDelegate, like below:

    class MyViewController: UIViewController, UITextFieldDelegate {
    
    }
    
  2. Set the delegate of your textfield: myTextField.delegate = self

  3. Implement the method in your view controller:

    textField(_:shouldChangeCharactersInRange:replacementString:)
    

All together:

class MyViewController: UIViewController, UITextFieldDelegate  // Set delegate to class

@IBOutlet var mytextField: UITextField             //  textfield variable

override func viewDidLoad() {
    super.viewDidLoad()
    mytextField.delegate = self                  // set delegate
}


func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange,
                       replacementString string: String) -> Bool
{
    let maxLength = 4
    let currentString: NSString = textField.text
    let newString: NSString =  currentString.stringByReplacingCharactersInRange(range, withString: string)

    return newString.length <= maxLength
}

For Swift 4

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let maxLength = 1
    let currentString: NSString = (textField.text ?? "") as NSString
    let newString: NSString =  currentString.replacingCharacters(in: range, with: string) as NSString

    return newString.length <= maxLength
}

For Swift 5

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let maxLength = 1
    let currentString = (textField.text ?? "") as NSString
    let newString = currentString.replacingCharacters(in: range, with: string)

    return newString.count <= maxLength
}

Allowing only a specified set of characters to be entered into a given text field

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    var result = true

    if mytextField == textField {
        if count(string) > 0 {
            let disallowedCharacterSet = NSCharacterSet(charactersInString: "0123456789.-").invertedSet
            let replacementStringIsLegal = string.rangeOfCharacterFromSet(disallowedCharacterSet) == nil
            result = replacementStringIsLegal
        }
    }

    return result
}

How to program an iOS text field that takes only numeric input with a maximum length

Itinerancy answered 12/7, 2015 at 0:41 Comment(10)
Thank you so much for the prompt reply! If I set this one textfield as the delegate would I be able to modify other textfields?Memphian
yes, and you will get the textfield in question (being edited ) as the first parameter textField in the method func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool Itinerancy
But where would I put in the second parameter? I don't reference myTextField again after I set it as a delegate.Memphian
Like if I wanted to make another textfield 0-9 only for phone numbers.Memphian
every time a textfield is being edited, the callback shouldChangeCharactersInRange is called, this is for all textfields, you receive the callback in the same place shouldChangeCharactersInRange and inside this method you can know which textfield is being edited thanks to the passed parameter textField you can for example give a tag for each textfield and test inside the shouldChangeCharactersInRange and for each textfield perform the validation of the contentItinerancy
@Memphian I have updated the answer with another example note the if mytextField == numberField { to check the textField that is being editedItinerancy
Does this particular solution allow the user to enter a backspace character once the user has hit the character limit? Would we need a way to let backspaces through?Fugal
@TheoBendixson , the more modern solution of simply using . editingChanged completely handles all such issues.Addendum
Suppose I have 2 textfields. Both require different max char limit, one require 10 char and other require 20 char. In that case what approach should I need to follow. Is there any way to make maxLength variable dynamic?Cognation
Isn't something missing from the source code near "class MyViewController"? The syntax highlighting is off.Farm
A
139

Modern Swift

Note that a lot of the example code online is extremely out of date.

Paste the following into any Swift file in your project, example "Handy.swift".

This fixes one of the silliest problems in iOS:

enter image description here

Your text fields now have a .maxLength.

It is completely OK to set that value in storyboard or set in code while the app is running.

// Handy.swift

import UIKit
private var __maxLengths = [UITextField: Int]()
extension UITextField {
    @IBInspectable var maxLength: Int {
        get {
            guard let l = __maxLengths[self] else {
               return 150 // (global default-limit. or just, Int.max)
            }
            return l
        }
        set {
            __maxLengths[self] = newValue
            addTarget(self, action: #selector(fix), for: .editingChanged)
        }
    }
    func fix(textField: UITextField) {
        let t = textField.text
        textField.text = t?.prefix(maxLength).string
    }
}

It's that simple.

An even simpler one-off version...

The above fixes all text fields in the whole project.

If you just want one particular text field to simply be limited to say "4", and that's that...

class PinCodeEntry: UITextField {
    
    override func didMoveToSuperview() {
        
        super.didMoveToSuperview()
        addTarget(self, action: #selector(fixMe), for: .editingChanged)
    }
    
    @objc private func fixMe() { text = text?.prefix(4) }
}

That's all there is to it.

(Here's a similar very useful tip relating to UITextView, https://mcmap.net/q/73259/-how-to-lose-margin-padding-in-uitextview )

Addendum answered 29/3, 2017 at 17:4 Comment(19)
That all this has to be done to achieve something so common and so simple blows my mind. They couldn't just give us a simple textField.maxLength built-in...anyway your solution is great, thanks!Hollingsworth
For Swift 4, this self.characters is deprecated. It is now just let c = selfWheezy
Cannot we do something like this for regex validation (like phoneNumber, emailId, userName)?Revolutionize
The solution is handy but the map of textfields at the top will actually produce a retain cycle.Subnormal
hi @AngelGarcíaOlloqui - it's an excellent point, in the unusual case where they're not just from storyboards, you'd have to attend to that. Good thinking!Addendum
super.didMoveToSuperview() "The default implementation of this method does nothing. Subclasses can override it to perform additional actions whenever the superview changes." Considering it calling super for that method is pointlessArthrospore
an excellent point @LeoDabus , thanks! I'll leave it there to help new programmers with the typical pattern; Happy new year!Addendum
This solution creates a new issue while typing in other languages like Mandarin, Korean, etc.Scarletscarlett
WARNING FOR THOSE USING THIS SOLUTION! This solution has some problems. One of them is that if the user types at the beginning of the textField, you are going to allow them to type the new character and the last one will be removed, also, the cursor will jump to the last character in the field. Another problem is that if you set the text programmatically, it will allow you to set a text bigger than the limit. Another problem occurs if you undo a change (CMD+Z with an external keyboard) it will crash if you tried to add a digit over the limit previously.Deccan
hi @Deccan ! the first three are desired behaviors, and depend on what you or the client wants. regarding the external keyboard undo issue, that's a great point, I did not think of testing with an external keyboard! I will try to repo that!Addendum
it gives me an error saying Expression type '()' is ambiguous without more context on prefixMontagu
hi @Addendum I posted my question here https://mcmap.net/q/75589/-create-max-character-length-in-uitextfield-using-ibinspectable-duplicate/6800631Montagu
@Addendum you need to update the post textField.text = String(textField.text!.prefix(maxLength)) and text = String(text!.prefix(4))Arthrospore
Prefix returns a substringArthrospore
I think since String started conforming to RangeReplaceableCollectionArthrospore
@Addendum You can safely force unwrap it. Its default value is an empty String. It will NEVER return nil. You can even set it to nil and it wont return nil after that.Arthrospore
hi @LeoDabus , you know, I wonder if that assumption in the specific UITextField class would confuse newer users; it's not something one can assume generally ... :OAddendum
You can warn them about this case being an exception :) As well as the reason why there is no need to call super.didMoveToSuperview()Arthrospore
The text property being optional allows you to assign an optional string to it without the need to unwrap its valueArthrospore
L
37

In Swift 4, simply use:

public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    return range.location < 10
}
Lennox answered 8/8, 2018 at 8:18 Comment(7)
It doesnt work. What if you tap in the middle of the string and you can type more than X chars.Excursionist
instead of range.location < 10, you can use textField.text.length < 10. This solution is simple and elegant.Emotive
You can use this solution: if textField.text?.count >= 12 { return false }Lennox
it doesn't work when past a text if you want to work in past action you should add string.count < MAX_LENGTHSquabble
This cannot work. Location is not the length of the string but the position of the cursor / selelction.Cryptonym
Worked in my case, only digits in textfieldSharitasharity
It should not be the correct answer. If you copy-paste a longer text it doesn't allow you modify it anymore because it will always return false. I can't believe it has so many upvotesCharlot
C
15

The same way Steven Schmatz did it but using Swift 3.0 :

//max Length
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
               replacementString string: String) -> Bool
{
    let maxLength = 4
    let currentString: NSString = textField.text! as NSString
    let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
    return newString.length <= maxLength
}
Cull answered 11/1, 2017 at 12:35 Comment(1)
There is no one here by the name "Steven Schmatz". What answer does it refer to? Is it SwiftMatt's answer? The other three possibilities are "Alaeddine", "ZaEeM ZaFaR", and "Cloy" (deleted answer - link-only answer).Farm
U
10

For Swift 5:

Just write one line to set the maximum character length:

 self.textField.maxLength = 10

For more details, see Max character limit of UITextField and allowed characters Swift. (Also credited.)

Undergird answered 28/7, 2019 at 6:50 Comment(1)
While this solution may seem straightforward, there is actually a lot more code that is required to implement this. This answer isn't very helpful by itself and the addition of an explanation and inclusion of other relevant pieces of code might be helpful.Palatable
F
8

Simple solution without using a delegate:

TEXT_FIELD.addTarget(self, action: #selector(editingChanged(sender:)), for: .editingChanged)


@objc private func editingChanged(sender: UITextField) {

        if let text = sender.text, text.count >= MAX_LENGHT {
            sender.text = String(text.dropLast(text.count - MAX_LENGHT))
            return
        }
}
Flavius answered 29/8, 2018 at 12:3 Comment(3)
This is the solution, simple and elegant, with no boilerplate code.Tonkin
Will that work? MAX_LENGHT looks like a misspelling. Why isn't it MAX_LENGTH? Where is it defined? Dictionary: lengthFarm
Defined nowhere :) I think his intention is for the reader of his comment to replace it with the wanted maximum length. Besides that, this answer should be the solution.Penhall
V
7

I think an extension is more handy for this. See the full answer here.

private var maxLengths = [UITextField: Int]()

// 2
extension UITextField {

  // 3
  @IBInspectable var maxLength: Int {
    get {
      // 4
      guard let length = maxLengths[self] else {
        return Int.max
      }
      return length
    }
    set {
      maxLengths[self] = newValue
      // 5
      addTarget(
        self,
        action: #selector(limitLength),
        forControlEvents: UIControlEvents.EditingChanged
      )
    }
  }

  func limitLength(textField: UITextField) {
    // 6
    guard let prospectiveText = textField.text
      where prospectiveText.characters.count > maxLength else {
        return
    }

    let selection = selectedTextRange
    // 7
    text = prospectiveText.substringWithRange(
      Range<String.Index>(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength))
    )
    selectedTextRange = selection
  }

}
Varicocele answered 11/7, 2016 at 12:28 Comment(0)
D
5

My Swift 4 version of shouldChangeCharactersIn

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

    guard let preText = textField.text as NSString?,
        preText.replacingCharacters(in: range, with: string).count <= MAX_TEXT_LENGTH else {
        return false
    }

    return true
}
Discontent answered 25/9, 2018 at 10:36 Comment(0)
S
4

Other solutions posted previously produce a retain cycle due to the textfield map. Besides, the maxLength property should be nullable if not set instead of artificial Int.max constructions; and the target will be set multiple times if maxLength is changed.

Here an updated solution for Swift4 with a weak map to prevent memory leaks and the other fixes

private var maxLengths = NSMapTable<UITextField, NSNumber>(keyOptions: NSPointerFunctions.Options.weakMemory, valueOptions: NSPointerFunctions.Options.strongMemory)

extension UITextField {

    var maxLength: Int? {
        get {
            return maxLengths.object(forKey: self)?.intValue
        }
        set {
            removeTarget(self, action: #selector(limitLength), for: .editingChanged)
            if let newValue = newValue {
                maxLengths.setObject(NSNumber(value: newValue), forKey: self)
                addTarget(self, action: #selector(limitLength), for: .editingChanged)
            } else {
                maxLengths.removeObject(forKey: self)
            }
        }
    }

    @IBInspectable var maxLengthInspectable: Int {
        get {
            return maxLength ?? Int.max
        }
        set {
            maxLength = newValue
        }
    }

    @objc private func limitLength(_ textField: UITextField) {
        guard let maxLength = maxLength, let prospectiveText = textField.text, prospectiveText.count > maxLength else {
            return
        }
        let selection = selectedTextRange
        text = String(prospectiveText[..<prospectiveText.index(from: maxLength)])
        selectedTextRange = selection
    }
}
Subnormal answered 4/4, 2018 at 10:38 Comment(1)
Thanks for your answer, Can u explain maxLengths please?Cabriole
F
3

I give a supplementary answer based on @Frouo. I think his answer is the most beautiful way. Because it's a common control we can reuse. And there isn't any leak problem here.

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

    // The method is used to cancel the check when using
    // the 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
    }


    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
    }

}
Fluor answered 6/2, 2018 at 12:53 Comment(1)
There is no one here by the name "Frouo". What answer does it refer to?Farm
C
3

Update for Fattie's answer:

extension UITextField {

    // Runtime key
    private struct AssociatedKeys {
        // Maximum length key
        static var maxlength: UInt8 = 0
        // Temporary string key
        static var tempString: UInt8 = 0
    }

    // Limit the maximum input length of the textfiled
    @IBInspectable var maxLength: Int {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.maxlength) as? Int ?? 0
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.maxlength, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            addTarget(self, action: #selector(handleEditingChanged(textField:)), for: .editingChanged)
        }
    }

    // Temporary string
    private var tempString: String? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.tempString) as? String
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.tempString, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }

    // When the text changes, process the amount of text in the input
    // box so that its length is within the controllable range.
    @objc private func handleEditingChanged(textField: UITextField) {

        // Special processing for the Chinese input method
        guard markedTextRange == nil else { return }

        if textField.text?.count == maxLength {

            // Set lastQualifiedString where text length == maximum length
            tempString = textField.text
        } else if textField.text?.count ?? 0 < maxLength {

            // Clear lastQualifiedString when text length > maxlength
            tempString = nil
        }

        // Keep the current text range in arcgives
        let archivesEditRange: UITextRange?

        if textField.text?.count ?? 0 > maxLength {

            // If text length > maximum length, remove last range and to move to -1 postion.
            let position = textField.position(from: safeTextPosition(selectedTextRange?.start), offset: -1) ?? textField.endOfDocument
            archivesEditRange = textField.textRange(from: safeTextPosition(position), to: safeTextPosition(position))
        } else {

            // Just set current select text range
            archivesEditRange = selectedTextRange
        }

        // Main handle string maximum length
        textField.text = tempString ?? String((textField.text ?? "").prefix(maxLength))

        // Last configuration edit text range
        textField.selectedTextRange = archivesEditRange
    }

    // Get safe textPosition
    private func safeTextPosition(_ optionlTextPosition: UITextPosition?) -> UITextPosition {

        /* beginningOfDocument -> The end of the the text document. */
        return optionlTextPosition ?? endOfDocument
    }
}
Chrisman answered 5/12, 2018 at 7:6 Comment(0)
P
3

Simply just check with the number of characters in the string

  1. Add a delegate to view controller and assign the delegate

    class YorsClassName : UITextFieldDelegate {
    
    }
    
  2. Check the number of characters allowed for the text field

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

Note: Here I checked for only characters allowed in textField.

Peevish answered 18/5, 2019 at 9:2 Comment(1)
What is meant by the last sentence? Can you elaborate? What is not checked? What is only checked? For example, do you mean "Here I only checked for characters allowed in textField"? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).Farm
D
3
  1. Set the delegate of your textfield:

     textField.delegate = self
    
  2. Implement the method in your view controller:

     // MARK: Text field delegate
    
     extension ViewController: UITextFieldDelegate {
         func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
             return range.location < maxLength (maxLength can be any maximum length you can define)
         }
     }
    
Distinctive answered 20/1, 2021 at 5:45 Comment(0)
F
2

I have something to add to Alaeddine's answer:

  1. Your view controller should conform to UITextFieldDelegate

     class MyViewController: UIViewController, UITextViewDelegate {
    
     }
    
  2. Set the delegate of your textfield:

    To set the delegate, you can control drag from the textfield to your view controller in the storyboard. I think this is preferable to setting it in code

  3. Implement the method in your view controller:

     textField(_:shouldChangeCharactersInRange:replacementString:)
    
Friar answered 19/12, 2015 at 5:34 Comment(0)
I
2

TextField Limit Character After Block the Text in Swift 4

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


    if textField == self.txtDescription {
        let maxLength = 200
        let currentString: NSString = textField.text! as NSString
        let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
        return newString.length <= maxLength
    }

    return true


}
Infra answered 16/10, 2019 at 5:43 Comment(0)
U
1

Here's a Swift 3.2+ alternative that avoids unnecessary string manipulation. In this case, the maximum length is 10:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let text = textField.text ?? ""

    return text.count - range.length + string.count <= 10
}
Unessential answered 11/12, 2017 at 19:1 Comment(0)
L
1

This answer is for Swift 4 and is pretty straightforward with the ability to let backspace through.

func textField(_ textField: UITextField,
               shouldChangeCharactersIn range: NSRange,
               replacementString string: String) -> Bool {
    return textField.text!.count < 10 || string == ""
}
Lagomorph answered 16/12, 2017 at 20:39 Comment(1)
This does not handle copy and pasteManymanya
E
1

This is working In Swift 4

Step 1: Set UITextFieldDelegate

class SignUPViewController: UIViewController , UITextFieldDelegate {

   @IBOutlet weak var userMobileNoTextFiled: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

Step 2: Set the delegate

        userMobileNoTextFiled.delegate = self                  // Set delegate
   }

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

Step 3: Call the function

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let maxLength = 10          // Set your need
        let currentString: NSString = textField.text! as NSString
        let newString: NSString =
            currentString.replacingCharacters(in: range, with: string) as NSString
        return newString.length <= maxLength
    }
}
Eardrum answered 1/5, 2018 at 5:43 Comment(0)
A
1

I use these steps. First set the delegate text field in viewdidload.

override func viewDidLoad() {
    super.viewDidLoad()

    textfield.delegate = self
}

And then shouldChangeCharactersIn after you include UITextFieldDelegate.

extension viewController: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let newLength = (textField.text?.utf16.count)! + string.utf16.count - range.length
        if newLength <= 8 {
            return true
        }
        else {
            return false
        }
    }
}
Airlie answered 15/5, 2019 at 7:51 Comment(0)
T
1

Just in case, don't forget to guard the range size before applying it to the string. Otherwise, you will get a crash if the user will do this:

  • Type maximum length text
  • Insert something (nothing will be inserted due to the length limitation, but iOS doesn't know about it)
  • Undo insertion (you get a crash, because the range will be greater than the actual string size)

Also, using iOS 13 users can accidentally trigger this by gestures

I suggest you add to your project this

extension String {
    func replace(with text: String, in range: NSRange) -> String? {
        // NOTE: NSString conversion is necessary to operate in the same symbol steps
        // Otherwise, you may not be able to delete an emoji, for example
        let current = NSString(string: self)
        guard range.location + range.length <= current.length else { return nil }
        return current.replacingCharacters(in: range, with: text)
    }
}

And use it like this:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    guard let newText = textView.text.replace(with: text, in: range) else { return false }
    return newText.count < maxNumberOfCharacters
    // NOTE: You may wanna trim the new text instead,
    // so the user will able to shove his long text at least partially
}

Otherwise, you will constantly be getting crashed in your app.

Teddi answered 26/10, 2019 at 11:35 Comment(0)
S
0

If you have multiple textField that have various length checks on one page I've found an easy and short solution.

class MultipleTextField: UIViewController {

    let MAX_LENGTH_TEXTFIELD_A = 10
    let MAX_LENGTH_TEXTFIELD_B = 11

    lazy var textFieldA: UITextField = {
        let textField = UITextField()
        textField.tag = MAX_LENGTH_TEXTFIELD_A
        textField.delegate = self
        return textField
    }()
    lazy var textFieldB: UITextField = {
        let textField = UITextField()
        textField.tag = MAX_LENGTH_TEXTFIELD_B
        textField.delegate = self
        return textField
    }()
}

extension MultipleTextField: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        return (range.location < textField.tag) && (string.count < textField.tag)
    }
}
Squabble answered 6/4, 2020 at 9:3 Comment(0)
C
0

When scrolling through these answers I could not fully puzzle the answer I was looking for (but that might have been me). I was looking for setting maximum characters on two textFields (but more is possible by extending the else) within one view. The solution I came which I also found the most clean was an extension. Here is the code just adjust the Place things here with your VC and textField.

extension PlaceYourViewControllerHere: UITextFieldDelegate {

private var maxCharacters: Int = 24

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let textFieldText = textField.text,
            let rangeOfTextToReplace = Range(range, in: textFieldText) else {
        return false
    }
    if textField == placeFirstTextfieldHere { maxCharacters = 64 } else { maxCharacters = 255 }
    let substringToReplace = textFieldText[rangeOfTextToReplace]
    let count = textFieldText.count - substringToReplace.count + string.count
    return count <= maxCharacters
    }

}

Edit: Do not forget the set a delegate on your textField.

        textField.delegate = self
Char answered 12/7, 2023 at 7:22 Comment(0)
P
-1
lazy var textField: UITextField = {
  let textField = UITextField()
  textField.addTarget(self, #selector(handleOnEditing), for .editingChanged)
  return textField
}()

//Set Delegate in ViewDidLoad textField.delegate = self

@objc func handleOnEditing() {
   let text = textField.text ?? ""
   let limit = 10
   textField.text = String(text.prefix(limit))
}
Paddie answered 27/7, 2022 at 5:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.