Set the maximum character length of a UITextField in Swift
Modern Swift
Note that much of the example code online regarding this problem is extremely out of date.
Paste the following into any Swift file in your project. (You can name the file anything, for example, "Handy.swift".)
This finally fixes one of the stupidest problems in iOS:
Your text fields now have a .maxLength
.
It is completely OK to set that value in storyboard during development, or, set it in code while the app is running.
// simply have this in any Swift file, say, 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.
Footnote - these days to safely truncate a String
in swift, you simply .prefix(n)
An even simpler one-off version...
The above fixes all text fields in your 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) }
}
Phew! That's all there is to it.
(Just BTW, here's a similar very useful tip relating to UITextView, https://stackoverflow.com/a/42333832/294884 )
For the OCD programmer (like me)...
As @LeoDabus reminds, .prefix
returns a substring. If you're incredibly caring, this
let t = textField.text
textField.text = t?.prefix(maxLength)
would be
if let t: String = textField.text {
textField.text = String(t.prefix(maxLength))
}
Enjoy!
Your view controller should conform to
UITextFieldDelegate
, like below:class MyViewController: UIViewController, UITextFieldDelegate { }
Set the delegate of your textfield:
myTextField.delegate = self
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 == numberField {
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