5

I have an iOS Xcode 7.3 Swift2 project I'm working on. It has different UITextFields that are limited to 3 digits, specifically only numbers. They are assigned to the UITextFieldDelegate and it's working well.

Here is where I limit them:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    guard let text = textField.text else { return true }
    let newLength = text.characters.count + string.characters.count - range.length
    let limitLength = 3
    if newLength > limitLength {
        return false
    }

    let numberOnly = NSCharacterSet.init(charactersInString: "0123456789")
    let stringFromTextField = NSCharacterSet.init(charactersInString: string)
    let strValid = numberOnly.isSupersetOfSet(stringFromTextField)

    return strValid
}

However, some of the UITextFields need to be limited to numbers still AND also limited to a single digit, how can I institute this in the section above, only for those specific UITextFields?

The names of the UITextFields that need to be single digits are:

widthInches
lengthInches

I tried placing this after the first guard section with no luck:

guard let text2 = widthInches.text else { return true }
let newLength2 = text2.characters.count + string.characters.count - range.length
let limitLength2 = 3
if newLength2 > limitLength2 {
    return false
}
ChallengerGuy
  • 2,385
  • 6
  • 27
  • 43
  • all of the answers here are **very out of date**, just do this http://stackoverflow.com/a/43099816/294884 – Fattie Mar 29 '17 at 17:05

5 Answers5

5

You can also try this code for limit textfield

actually i am using here textfield tag. Because custom textfield. If you using custom textfield like TextfieldEffect in this condition tag will help you for limit of Textfield.

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

        
        if textField.tag == txtMobileNumber.tag{
            let maxLength = 10
            let currentString: NSString = textField.text!
            let newString: NSString =
            currentString.stringByReplacingCharactersInRange(range, withString: string)
            return newString.length <= maxLength
        }
        
        return true
    }

I hope this will help you.

Community
  • 1
  • 1
Anand Nimje
  • 6,163
  • 4
  • 24
  • 43
  • I didn't know you could add tags to UITextFields, let alone use them in the UITextFieldDelegate. I will have to look into this in the future. Thank you. – ChallengerGuy Jun 10 '16 at 19:08
  • Actually why i used this because i am not using UITextfield i am using custom textfield thats why i faced problem then i got solution for that with using Tag. – Anand Nimje Jun 11 '16 at 04:37
2

The function shouldChangeCharactersInRange passes in the particular textField as one of its parameters. You can look at that and see if it points to the same instance as the ones you want to shorten, like this:

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

    guard let text = textField.text else { return true }
    var limitLength = 3
    if textField == widthInches || textField == lengthInches {
      limitLength = 1
    }

    let newLength = text.characters.count + string.characters.count - range.length
    if newLength > limitLength {
      return false
    }

    let numberOnly = NSCharacterSet.init(charactersInString: "0123456789")
    let stringFromTextField = NSCharacterSet.init(charactersInString: string)
    let strValid = numberOnly.isSupersetOfSet(stringFromTextField)

    return strValid
  }

Assuming all other requirements are the same (numbers only) this will do the trick.

There are other ways, for example - you could subclass UITextField and add a limitLength field, then use that field in the delegate, but that's probably overkill for just 2 exceptions.

DJohnson
  • 929
  • 4
  • 15
  • Thank you. I don't think doing a subclass is necessary. The other way makes perfect sense. – ChallengerGuy Jun 09 '16 at 13:51
  • 1
    I did end up needing more textFields than I originally thought that were needing the limit of 1. I went with what you said, but instead of an if..then statement, went with a case statement for multiple UITextFields. Works perfectly! – ChallengerGuy Jun 09 '16 at 14:12
1

Hello in your func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool the textField param is the textField that has trigger this event so you can check with yours textfields objects and if are equal to one of them then make a different behavior

I hope this helps you,

Reinier Melian
  • 20,519
  • 3
  • 38
  • 55
1
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {  
    return (textField.text?.utf16.count ?? 0) + string.utf16.count - range.length <= TEXT_FIELD_LIMIT
}

This counts the number of characters based on UTF-16 representation, as range.length is given in UTF-16 base. If you need to count the number of characters in other ways, the expression may get longer. If you want only numbers to be input use textField.keyboardType = UIKeyboardTypeDecimalPad . If you want specific textFields then add tags and compare them and if they are equal you can implement your specific code for that.

Check this link for detailed answer : http://www.globalnerdy.com/2016/05/24/a-better-way-to-program-ios-text-fields-that-have-maximum-lengths-and-accept-or-reject-specific-characters/

  • This has nothing to do with the question. – rmaddy Jun 08 '16 at 16:51
  • I understand the keyboard type, however on the iPad it also has characters like $, &, etc. that was the reason for specifying the actual numbers to use in my code. iPhone was no big deal. – ChallengerGuy Jun 08 '16 at 18:30
0

update for swift 3 add this class and call it TextField.swift. it will add the limit input on the storyboard.

  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
    // Any text field with a set max length will call the limitLength
    // method any time it's edited (i.e. when the user adds, removes,
    // cuts, or pastes characters to/from the text field).
      addTarget(
          self,
          action: #selector(limitLength),
          for: UIControlEvents.editingChanged
      )
  }
 }

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

      // If the change in the text field's contents will exceed its maximum 
     length,
     // allow only the first [maxLength] characters of the resulting text.
     let selection = selectedTextRange

    // text = prospectiveText.substring(with:Range<String.Index>
    (prospectiveText.startIndex ..< prospectiveText.index(after: maxLength))
    let s = prospectiveText

      // Get range 4 places from the start, and 6 from the end.
     let c = s.characters;

      let r = c.index(c.startIndex, offsetBy: 0)..<c.index(c.endIndex, offsetBy:   maxLength - c.count)
       text = s[r]


     // Access the string by the range.


     selectedTextRange = selection
    }

   }

or download here - >TextField.swift

Community
  • 1
  • 1
juzt
  • 17
  • 2