Skip to content

Instantly share code, notes, and snippets.

@andrealufino
Forked from dedeexe/UITextField+MaskPattern.swift
Last active December 24, 2017 13:41
Show Gist options
  • Save andrealufino/9452a6498a5076d693ff56070d63fe0d to your computer and use it in GitHub Desktop.
Save andrealufino/9452a6498a5076d693ff56070d63fe0d to your computer and use it in GitHub Desktop.
Adding Mask to a TextField
extension UITextField {
private struct FKFieldPatterns {
static var pattern = "pattern"
static var replacementChar = "replacementChar"
static var allowNumbers = "allowNumbers"
static var allowText = "allowText"
}
private var pattern : String {
if let result = objc_getAssociatedObject(self, &FKFieldPatterns.pattern) as? String {
return result
}
return ""
}
private var replacementChar : String {
if let result = objc_getAssociatedObject(self, &FKFieldPatterns.replacementChar) as? String {
return result
}
return ""
}
private var allowText : Bool {
if let result = objc_getAssociatedObject(self, &FKFieldPatterns.allowText) as? Bool {
return result
}
return true
}
private var allowNumbers : Bool {
if let result = objc_getAssociatedObject(self, &FKFieldPatterns.allowNumbers) as? Bool {
return result
}
return true
}
func formatPattern(pattern:String?=nil, replacementChar:String?=nil, allowText:Bool=true, allowNumbers:Bool=true)
{
objc_setAssociatedObject(self, &FKFieldPatterns.pattern, pattern ?? "", .OBJC_ASSOCIATION_RETAIN)
objc_setAssociatedObject(self, &FKFieldPatterns.replacementChar, replacementChar ?? "*", .OBJC_ASSOCIATION_RETAIN)
objc_setAssociatedObject(self, &FKFieldPatterns.allowNumbers, allowNumbers, .OBJC_ASSOCIATION_RETAIN)
objc_setAssociatedObject(self, &FKFieldPatterns.allowText, allowText, .OBJC_ASSOCIATION_RETAIN)
registerNotifications()
}
private func registerNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(textDidChange), name: NSNotification.Name(rawValue: "UITextFieldTextDidChangeNotification"), object: self)
}
private func removeNotifications() {
NotificationCenter.default.removeObserver(self)
}
func prepareString(string:String) -> String
{
var charSet : CharacterSet!
if allowText && allowNumbers {
charSet = CharacterSet.alphanumerics.inverted as CharacterSet
}
else if allowText {
charSet = CharacterSet.letters.inverted as CharacterSet
}
else if allowNumbers {
charSet = CharacterSet.decimalDigits.inverted as CharacterSet
}
let result = string.components(separatedBy: charSet)
return result.joined(separator: "")
}
func textDidChange(notification : NSNotification) {
guard let text = self.text else {
return
}
if text.characters.count > 0 && pattern.characters.count > 0
{
var finalText = ""
var stop = false
let tempString = prepareString(string: text)
var formatIndex = pattern.startIndex
var tempIndex = tempString.startIndex
while !stop
{
let formattingPatternRange = formatIndex ..< pattern.index(formatIndex, offsetBy: 1)
if pattern.substring(with: formattingPatternRange) != String(replacementChar) {
finalText = finalText.appending(pattern.substring(with: formattingPatternRange))
} else if tempString.characters.count > 0 {
let pureStringRange = tempIndex ..< tempString.index(tempIndex, offsetBy: 1)
finalText = finalText.appending(tempString.substring(with: pureStringRange))
tempIndex = tempString.index(tempIndex, offsetBy: 1)
}
formatIndex = pattern.index(formatIndex, offsetBy: 1)
if formatIndex >= pattern.endIndex || tempIndex >= tempString.endIndex {
stop = true
}
self.text = finalText
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment