A fully customizable formatter used to create masks for texts.
let mask = "##/$$-@@"
let rules = [
MaskedFormatter.Rule(maskCharacter: "#", validation: { $0.isNumber }),
MaskedFormatter.Rule(maskCharacter: "$", validation: { $0.isLetter }),
MaskedFormatter.Rule(maskCharacter: "@", validation: { (Int(String($0)) ?? 0) >= 5 })
]
let maskedFormatter = MaskedFormatter(mask: mask, rules: rules)
let input = "123ABC456"
let output = maskedFormatter.string(for: input)
print(output!)
// "12/AB-56"
import MaskedFormatter
For instance, an "expiration date" mask, commonly used for credit card forms, can be defined as such:
let mask = "##/##"
Using the same example for an "expiration date" mask, this is how our rule would look like:
let rule = MaskedFormatter.Rule(maskCharacter: "#", validation: { $0.isNumber })
let maskedFormatter = MaskedFormatter(mask: mask, rules: [rule])
let input = "1234"
let output = maskedFormatter.string(for: input)
print(output!)
// "12/34"
For instance, by inheriting MaskedFormatter:
class CreditCardFormatter: MaskedFormatter {
init() {
let mask = "#### #### #### ####"
let rule = MaskedFormatter.Rule(maskCharacter: "#", validation: { $0.isNumber })
super.init(mask: mask, rules: [rule])
}
...
}
Mask a UITextField in "realtime" by listening to changes in the textfield:
let textField = UITextField()
textField.addTarget(self,
action: #selector(textFieldDidChange(_:)),
for: .editingChanged)
...
@objc func textFieldDidChange(_ textField: UITextField) {
textField.text = maskedFormatter.string(for: textField.text)
}
Mask a TextField in "realtime" through onChange
:
@State var text: String
...
TextField(placeholder, text: $text)
.onChange(of: text) { value in
text = maskedFormatter.string(for: text) ?? ""
}
MaskedFormatter.Rule(maskCharacter: Character, validation: @escaping (Character) -> Bool)
Rules will tell the formatter which characters from the mask are supposed to be replaced by what (letter, number, etc)
In our "expiration date" mask example (##/##
), we have two different characters, #
and /
. We want to replace #
, thus we will create a rule for that character.
MaskedFormatter.Rule(maskCharacter: "#", validation: { ... })
In order to tell which input is valid for that specific character, we use the validation parameter. This parameter receives a Character and returns a Bool:
MaskedFormatter.Rule(maskCharacter: "#", validation: { (char: Character) -> Bool in
...
})
In our example, we want the #
character to be replaced by a number, so we can check char
and see if it is a number:
MaskedFormatter.Rule(maskCharacter: "#", validation: { (char: Character) -> Bool in
char.isNumber
})
Now we can use this rule in one or more MaskedFormatters:
let rule = MaskedFormatter.Rule(maskCharacter: "#", validation: { $0.isNumber })
let formatter1 = MaskedFormatter(mask: "##", rules: [rule])
let formatter2 = MaskedFormatter(mask: "#/#", rules: [rule])