28

I would like to count the character when user keep typing in UITextField with swift.

Image of Field and Label:

enter image description here

I have already placed UITextField and UILabel, just haven't found any information on Stack overflow, also if you can do one in UITextView I also appreciate it.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Brian Nezhad
  • 6,148
  • 9
  • 44
  • 69

12 Answers12

31

To use the function below you need to implement the UITextFieldDelegate protocol on the text field you want to count. This gets called every time the UITextFields text changes:

Your class declaration should look something like this

class ViewController: UIViewController, UITextFieldDelegate

You should have an @IBOutlet similar to this

@IBOutlet var txtValue: UITextField

Set the UITextField s delegate to self.

override func viewDidLoad() {
    super.viewDidLoad()
    txtValue.delegate = self                
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let newLength = count(textField.text.utf16) + count(string.utf16) - range.length

    mylabel.text =  String(newLength) // Set value of the label
    // myCounter = newLength // Optional: Save this value
    // return newLength <= 25 // Optional: Set limits on input. 
    return true
}

Note that this function is called on all UITextFields so if you have several UITextFields you will need to add a logic to know witch one is calling this function.

Dan Leonard
  • 3,325
  • 1
  • 20
  • 32
Icaro
  • 14,585
  • 6
  • 60
  • 75
22

A very elegant and neat solution exists using UITextFieldDelegate. My solution uses the concept of selectors. In a selector you tell your compiler what function/action to perform when a particular event happens. In this case - typing in textfield. Make sure that you have set the textField delegate in storyboard.

override func viewDidLoad() {
   super.viewDidLoad()
   yourTextField.addTarget(self, action: #selector(YourViewController.textFieldDidChange(_:)), for: UIControlEvents.EditingChanged)
}

@objc func textFieldDidChange(textField : UITextField){
   label.text = yourTextField.text?.count
}
Yash Tamakuwala
  • 1,789
  • 1
  • 24
  • 33
13

For multiple UITextView

enter image description here

class ViewController: UIViewController, UITextViewDelegate {

 @IBOutlet weak var ticketSummaryTV: UITextView!
 @IBOutlet weak var ticketDescriptionTV: UITextView!

 @IBOutlet weak var summaryCountLbl: UILabel!
 @IBOutlet weak var descriptionCountLbl: UILabel!

 override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.

    ticketSummaryTV.delegate = self
    ticketDescriptionTV.delegate = self

    self.updateCharacterCount()
 }

 func updateCharacterCount() {
    let summaryCount = self.ticketSummaryTV.text.characters.count
    let descriptionCount = self.ticketDescriptionTV.text.characters.count

    self.summaryCountLbl.text = "\((0) + summaryCount)/50"

    self.descriptionCountLbl.text = "\((0) + descriptionCount)/500"
 }

 func textViewDidChange(_ textView: UITextView) {
    self.updateCharacterCount()
 }


 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool{
    if(textView == ticketSummaryTV){
       return textView.text.characters.count +  (text.characters.count - range.length) <= 50
    }else if(textView == ticketDescriptionTV){
        return textView.text.characters.count +  (text.characters.count - range.length) <= 500
    }
    return false
 }
}
MinnuKaAnae
  • 1,646
  • 3
  • 23
  • 35
6

This will only allow your textfield input 14 char

class ViewController: UIViewController,UITextFieldDelegate {

@IBOutlet weak var textfield: UITextField!
@IBOutlet weak var label: UILabel!
override func viewDidLoad() {
    super.viewDidLoad()
    self.label.text = "14"
    self.textfield.delegate = self
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let newLength = count(textField.text.utf16) + count(string.utf16) - range.length
    if(newLength <= 14){
        self.label.text = "\(14 - newLength)"
        return true
    }else{
        return false
    }
}
}

And Screenshot

enter image description here

Leo
  • 24,596
  • 11
  • 71
  • 92
3
In Swift
viewDidLoad {
self.yourTextView.delegate = self
self.updateCharacterCount()
}

func updateCharacterCount() {
    self.yourLabel.text = "\((65) - self.yourTextView.text.characters.count)"  
}

func textViewDidChange(textView: UITextView) {
    self.updateCharacterCount()
}


func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    self.updateCharacterCount()
    return textView.text.characters.count +  (text.characters.count - range.length) <= 65
}
guest
  • 31
  • 1
3

Swift 5.1

Add viewController delegate

final class CreditCardViewController : BaseViewController , UITextFieldDelegate {

    @IBOutlet var cvvTextField: UITextField!

Add viewDidLoad()

cvvTextField.delegate = self

And add delegate function.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if(textField == cvvTextField){
            let characterCountLimit = 3
            let startingLength = textField.text?.count ?? 0
            let lengthToAdd = string.count
            let lengthToReplace = range.length

            let newLength = startingLength + lengthToAdd - lengthToReplace

            return newLength <= characterCountLimit
        }

        return true
    }
ikbal
  • 1,110
  • 12
  • 21
1

Swift 5.3

Add UITextFieldDelegate in you viewController with outlets

class ViewController: UIViewController, UITextFieldDelegate{
     @IBOutlet weak var txtGroupName: UITextField!
     @IBOutlet weak var lblWordCount: UILabel!

Add textfeild delegate in your viewDidLoad() like below

override func viewDidLoad() {
   super.viewDidLoad()
   txtGroupName.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControl.Event.editingChanged)
  }
    
   @objc func textFieldDidChange(textField : UITextField){
    self.lblWordCount.text = "\(self.txtGroupName.text!.count)/"+"\(65)"
  }

We have set also meximum text limit 65 . you can replace 65 to what you want.

extension viewController:UITextFieldDelegate{
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if !(textField.text?.isEmpty ?? true){
            return textField.text!.count +  (string.count - range.length) <= 65
        }
        return true
    }
}

It's output is like below

output

pansora abhay
  • 892
  • 10
  • 16
0

Here's how you could do it in Swift 3/4.

First, make sure you've got your textField's delegate set in viewDidLoad.

yourTextField.delegate = self

Then, implement shouldChangeCharactersIn:

extension YourViewController: UITextFieldDelegate {
    func textField(_ textFieldToChange: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
      // limit to 4 characters
      let characterCountLimit = 4

      // We need to figure out how many characters would be in the string after the change happens
      let startingLength = textFieldToChange.text?.characters.count ?? 0
      let lengthToAdd = string.characters.count
      let lengthToReplace = range.length

      let newLength = startingLength + lengthToAdd - lengthToReplace

      return newLength <= characterCountLimit
    } 
}

Additional details here

Adrian
  • 16,233
  • 18
  • 112
  • 180
0

Swift 4 for UITextView change text event UITextViewDelegate

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {

}
MinnuKaAnae
  • 1,646
  • 3
  • 23
  • 35
mr.byte
  • 21
  • 5
0

UITextView count while typing in Swift:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {

        let textCount = textView.text?.count ?? 0 + text.count - range.length
        self.textCountLabel.text  = "\(textCount)"
        return true
    }
Cfun
  • 8,442
  • 4
  • 30
  • 62
0

Simple...

Add a UITextViewDelegate to your class header like this...

class ViewController: UIViewController, UITextFieldDelegate { ... }

Add the @IBOutlet to both the UILabel and the UITextView like so...

@IBOutlet weak var characterCountLabel: UILabel!
@IBOutlet var characterTextField: UITextView!

Then add the following delegate to the viewDidLoad() function...

override func viewDidLoad() {
    super.viewDidLoad()
    self.characterTextField.delegate = self // required for character counter
}

Finally, just create a func for the textViewDidChange delegate method...

func textViewDidChange(_ textView: UITextView) {
    self.characterCountLabel.text = String("\(textView.text.count)")
}

I personally checked and verified this simple way to add a text counter for your UITextView and output it to a UILabel and it works!

WhiteEagle
  • 97
  • 1
  • 4
0
 func updateCharacterCount() {
           let count = DescriptionTextview.text.count
           descountlabel.text = "\((0) + count)/140"
       }

extension DescriptionCollectionViewCell: UITextViewDelegate{

    func textViewDidChange(_ textView: UITextView) {
            descountlabel.becomeFirstResponder()
            self.updateCharacterCount()
        }

    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool{
           let generator = UINotificationFeedbackGenerator()
           let count = textView.text.count +  (text.count - range.length)
           if count <= 140 {
               return true
           }else{
               generator.notificationOccurred(.error)
               return false
           }
    }

}
Venky
  • 1