-1

I have written below code to validate text input in textfield.

else if (textField == txtField_Password)
    {
        let charSet = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@$&*!")
        let charLength = (txtField_Password.text!.count) + (string.count) - range.length

        for i in 0..<string.count
        {
            let c = (string as NSString).character(at: i)
            if (!((charSet as NSCharacterSet).characterIsMember(c)))
            {
                return false
            }
        }
        return (charLength > 20) ? false : true
    }

Can anyone help me to convert character(at:) and characterIsMember() part to its swift equivalent in the above code.

AtulParmar
  • 4,358
  • 1
  • 24
  • 45
Yash Jadhav
  • 95
  • 1
  • 14

4 Answers4

4

You can simplify the logic just by checking the range of the inverted character set. If the string contains only allowed characters the function returns nil.

else if textField == txtField_Password {
    let charLength = txtField_Password.text!.utf8.count + string.utf8.count - range.length
    let charSet = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@$&*!")
    return string.rangeOfCharacter(from: charSet.inverted) == nil && charLength < 21
}
vadian
  • 274,689
  • 30
  • 353
  • 361
  • I implemented your answer and it is working. I just wanted to ask why to use utf8 in string.utf8.count – Yash Jadhav Mar 01 '19 at 11:42
  • 1
    A single character can contain more than one byte, counting the utf8 representation of the string makes it more consistent. – vadian Mar 01 '19 at 12:03
1

Note that there is a simpler way to implement what you want using a regular expression:

let currentText = (textField.text ?? "") as NSString
let newText = currentText.replacingCharacters(in: range, with: string)

let pattern = "^[a-zA-Z0-9@$&*!]{0,20}$"
return newText.range(of: pattern, options: .regularExpression) != nil
Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • Why use of NSString? – Yash Jadhav Mar 01 '19 at 12:39
  • @YashArunJadhav Because `replacingCharacters` with `NSRange` is defined only on `NSString` and using `NSRange` with swift `String` is basically impossible. Note that `newText` is a `String`. – Sulthan Mar 01 '19 at 12:42
  • Can you please try to implement your answer with only swift. – Yash Jadhav Mar 01 '19 at 12:46
  • @YashArunJadhav This is pure Swift. You cannot ignore the fact that `UIKit` was written in Objective-C and uses Objective-C types like `NSRange`. – Sulthan Mar 01 '19 at 12:53
0

You could work with something along these lines. I appreciate this is a bit rough and ready but should work:

charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@$&*!"

if txtField_Password.text!.count <= 20 {

    for i in 0..<str.count
    {
        let c = Array(str)[i]

        let cString = String(c)

        if charSet.contains(cString) {
            return false
           }
        }

    } else {
        return false
    }
Gareth Miller
  • 332
  • 1
  • 3
  • 10
0

Use rangeOfCharacter:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
       let specialCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@$&*!"


       let characterSet = CharacterSet(charactersIn: specialCharacters)

       guard let lengh = textfield.text else {return} 
       if lengh.count >= 20 {
         // text exceeded 20 characters. Do something 
       }     

       if (string.rangeOfCharacter(from: characterSet) != nil) {
              print("matched")
              return true
          } else { 
              print("not matched")
       }

    return true
 }
excitedmicrobe
  • 2,338
  • 1
  • 14
  • 30