6

I am creating a trivia application that asks for a username on start up. I'd like to make it impossible to use characters such as #$@!^& etc (also including "space"). I took a look at this post here but it is written entirely in Objective-C. Thanks in advance.

Community
  • 1
  • 1
Dylan Ireland
  • 910
  • 9
  • 11

8 Answers8

5

Swift 4 iOS 11.2.x based on using an extension, tests to see if a string is a valid hex number in this example.

extension String {

var containsValidCharacter: Bool {
    guard self != "" else { return true }
    let hexSet = CharacterSet(charactersIn: "1234567890ABCDEFabcdef")
    let newSet = CharacterSet(charactersIn: self)
    return hexSet.isSuperset(of: newSet)
  }
}

You use it like with the UITextFieldDelegate.

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

Although I read in an earlier post that CharacterSets do not support characters that are composed of more than one Unicode.Scalar; so use with caution I guess.

user3069232
  • 7,063
  • 6
  • 36
  • 61
3

Since you're explicitly asking for Swift, I've translated the top asnwer in the linked question.

let notAllowedCharacters = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";

func textField(
    textField: UITextField,
    shouldChangeCharactersInRange range: NSRange,
    replacementString string: String)
    -> Bool
{
    let set = NSCharacterSet(charactersInString: notAllowedCharacters);
    let inverted = set.invertedSet;

    let filtered = string
        .componentsSeparatedByCharactersInSet(inverted)
        .joinWithSeparator("");
    return filtered != string;

}
Evdzhan Mustafa
  • 3,126
  • 1
  • 20
  • 37
2
internal func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool{
     if let text = string{
           if text == "#" || text == "$" || text == "!"{ \\and so on
              return false
           }
     }
     return true
}
Andrew McKinley
  • 1,115
  • 1
  • 6
  • 11
  • Assumes replacement string is a single character, but it can be more when pasting a string – Dale May 21 '17 at 07:03
1

Swift 2.3

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

        let characters = ["#", "$", "!", "&","@"]
        for character in characters{
            if string == character{
                print("This characters are not allowed")
                return false
            }
        }
}
fs_tigre
  • 9,459
  • 12
  • 53
  • 111
1

So this is probably the most robust way to restrict Spaces. Using this user won't be able to Paste/Type Whitespaces

This is how you can Implement using Swift 3.

Add below mentioned extension snippet to a Swift file;

extension String {

var containsWhitespace: Bool {
    for scalar in unicodeScalars {
        switch scalar.value {
        case 0x20:
            return true
        default:
            continue
        }
    }
    return false
  }
}

In your ViewController Swift file drag out your Editing Changed Instance and a Referencing Outlet of UITextField from Storyboard, the one mentioned in picture below:

enter image description here

Use the dragged Instances as mentioned below:

Referencing Outlet as:

@IBOutlet weak var textField: UITextField!

and Editing Changed as:

 @IBAction func textChanged(_ sender: UITextField) {
    if (textField.text!.containsWhitespace) == true {
        print("Restrict/Delete Whitespace")
        emailField.deleteBackward()
    } else {
        print("If Its not Whitespace, Its allowed.")
    }
}

This will detect and remove whitespace as soon as user tries to type/paste it.

Codetard
  • 2,026
  • 22
  • 33
1

Swift 4 iOS 11.2.x based on using an extension, tests to see if a string is a valid hex number in this example.

extension String {

var containsValidCharacter: Bool {
    guard self != "" else { return true }
    let hexSet = CharacterSet(charactersIn: "1234567890ABCDEFabcdef")
    let newSet = CharacterSet(charactersIn: self)
    return hexSet.isSuperset(of: newSet)
  }
}

You use it like with the UITextFieldDelegate.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    return (string.containsValidCharacter)
}
user3069232
  • 7,063
  • 6
  • 36
  • 61
0

Swift : 3 and a different approach:

Add a target function for the text field change in your viewDidLoad:

    override func viewDidLoad() {
    super.viewDidLoad()
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
 }

in the target function, simply detect the entered char and replace it with blank. I have tested it and it prevents the user from entering any non desirable characters in the text field.

 func textFieldDidChange(textField: UITextField) {

    if let textInField = textField.text{
        if let lastChar = textInField.characters.last{

            //here include more characters which you don't want user to put in the text field
            if(lastChar == "*")
            {

                textField.text  = textInField.substring(to: textInField.index(before: textInField.endIndex))

            }
        }
    }

}
nitinsh99
  • 3,012
  • 3
  • 37
  • 73
0

Adding on to what @Evdzhan Mustafa said. You want to add a return statement in case the string is empty. Without it you won't be able to delete your text. Modified Code Below:

Swift 3 Version

let notAllowedCharacters = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if string.isEmpty{
        return true
    }

    print("String: \(string)")
    let set = NSCharacterSet(charactersIn: notAllowedCharacters);
    let inverted = set.inverted;

    let filtered = string.components(separatedBy: inverted).joined(separator: "")
    print("String Filtered: \(filtered)")
    return filtered != string;
}
Eric Aya
  • 68,765
  • 33
  • 165
  • 232
  • lose those semicolons – Dale May 21 '17 at 07:04
  • Had the idea that regex might be an easier way to filter the characters. Changed the models here to use regex instead. The result feels a lot more flexible. – Jeff Muir May 26 '17 at 01:22
  • 1
    Swift 3 examples with regex Check for 0-9: `if !(string.range(of:"^[0-9]+$", options: .regularExpression) != nil) { valid = false }` Check for 0-9, A-Z: `if !(string.range(of:"^[0-9A-Z]+$", options: .regularExpression) != nil) { valid = false }` – Jeff Muir May 26 '17 at 01:37