0

I have a textField to input a Canadian postal code. And I am using the following code to ensure the formatting is correct or else show an alert saying the formatting is incorrect. This is working with no problem on saveBtnClick; but I cant type in the field as it continues returning false into the textField because of the validZipCode function.I also need make sure the maximum length of characters for this field does not exceed 7 characters so the user cant type more than seven characters. I see many solutions only for setting the maximum length; but cant figure out how to do this with an existing condition that I mentioned here for postal code validation. Here is my current code:

@IBOutlet weak var postalCodeTextField: UITextField!

override func viewDidLoad() {
    phoneNumberTextField.delegate = self
    postalCodeTextField.delegate = self
}

func validZipCode(postalCode:String)->String{
    let postalcodeRegex = "^[a-zA-Z][0-9][a-zA-Z][- ]*[0-9][a-zA-Z][0-9]$"
    let pinPredicate = NSPredicate(format: "SELF MATCHES %@", postalcodeRegex)
    let bool = pinPredicate.evaluate(with: postalCode) as Bool
  return bool.description
}

@IBAction func saveBtnClicked(_ sender: Any) {

    let isPostalCodeValid = validZipCode(postalCode: postalCodeTextField.text ?? "")

    if isPostalCodeValid == "false" {

        simpleAlert(title: "Error!", msg: "Please enter a valid CA postal code")

    } else
        if isPostalCodeValid == "true" {
       //the postalCaode is correct formatting
    }

}




func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let text = textField.text else { return false }
        let newString = (text as NSString).replacingCharacters(in: range, with: string)

    if textField == phoneNumberTextField {
        textField.text = formattedNumber(number: newString)
    } else

        if textField == postalCodeTextField {
            textField.text = validZipCode(postalCode: newString)
    }

    return false
}
user12669401
  • 229
  • 4
  • 12

1 Answers1

1

The function validZipCode would always return false if we pass single character to it. So ,validate the predicate on click of saveButton.

class ViewController: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var postalCodeTextField: UITextField!

       override func viewDidLoad() {
            postalCodeTextField.delegate = self
        }

        func validZipCode(postalCode:String)->Bool{
              let postalcodeRegex = "^[a-zA-Z][0-9][a-zA-Z][- ]*[0-9][a-zA-Z][0-9]$"
            let pinPredicate = NSPredicate(format: "SELF MATCHES %@", postalcodeRegex)
            let bool = pinPredicate.evaluate(with: postalCode) as Bool
            return bool
        }

        @IBAction func saveBtnClicked(_ sender: Any) {

            let isPostalCodeValid = validZipCode(postalCode: postalCodeTextField.text ?? "")

            if isPostalCodeValid == false {
                print("false")
               // simpleAlert(title: "Error!", msg: "Please enter a valid CA postal code")

            } else
                if isPostalCodeValid == true {
                    print("true")
               //the postalCaode is correct formatting
            }

        }

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

            let currentText = textField.text ?? ""
             guard let stringRange = Range(range, in: currentText) else { return false }

            if textField == postalCodeTextField {
                // add their new text to the existing text
                let updatedText = currentText.replacingCharacters(in: stringRange, with: string)

                // make sure the result is under 7 characters
                return updatedText.count <= 7
            }else{
                return true
            }
        }

    }

Hope this helps !!

  • This is Great. Thank you! Do you how I can also have the postal code include a space after the 3th character? so when you type in there the result would look like `XXX XXX` Which is 7 in total and the fourth is always a space – user12669401 May 06 '20 at 21:37
  • 1
    You can modify the delegate methods as, if textField == postalCodeTextField { // add their new text to the existing text let updatedText = currentText.replacingCharacters(in: stringRange, with: string) if(currentText.count == 3){ postalCodeTextField.text = postalCodeTextField.text! + " " } // make sure the result is under 7 characters return updatedText.count <= 7 } – Vinayaka S Yattinahalli May 07 '20 at 03:13
  • 1
    I actually did that; but the problem is when I tried to backspace and delete; once it gets to character 3 it doesnt let the user to delete any further since the character.count goes from 4 to 3 - and here were are saying at 3 characters put a space which makes it abck to 4 characters – user12669401 May 07 '20 at 03:28
  • 1
    Ok so I used this solution to detect if we are backspacing and in that case I dont input space. otherwise I put space : https://stackoverflow.com/questions/29504304/detect-backspace-event-in-uitextfield – user12669401 May 07 '20 at 03:32