I have text label which has phone number in it. I mask the phone number when user is typing so that in shouldChangeCharactersIn function;
I get user input (string)
Add that input to text which is already written in UITextField
Mask text and set it to UITextField
Return false
My question is that after I set text of UITextfield (delete or add new character UITextField, cursor moves to the end but I want it to stay in the same position. (By meaning same position, I mean same when I don't implement shouldChangeCharactersIn function) How can I do that? Thank you.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string)) else {
return false
}
if let text = textField.text {
let newLength = text.count + string.count - range.length
let newText = text + string
let textFieldText: NSString = (textField.text ?? "") as NSString
let txtAfterUpdate = textFieldText.replacingCharacters(in: range, with: string)
if(newLength <= 15){
//textField.text = txtAfterUpdate
textField.text = txtAfterUpdate.digits.applyPatternOnNumbers()
return false
}
return newLength <= 15
}
return true
}
Mask Function:
func applyPatternOnNumbers(pattern: String = "(###) ### ## ##", replacmentCharacter: Character = "#") -> String {
var pureNumber = self.replacingOccurrences( of: "[^0-9]", with: "", options: .regularExpression)
for index in 0 ..< pattern.count {
guard index < pureNumber.count else { return pureNumber }
let stringIndex = String.Index(encodedOffset: index)
let patternCharacter = pattern[stringIndex]
guard patternCharacter != replacmentCharacter else { continue }
pureNumber.insert(patternCharacter, at: stringIndex)
}
return pureNumber
}
What I want in GIF
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string)) else {
return false
}
if let text = textField.text {
let newLength = text.count + string.count - range.length
let newText = text + string
let textFieldText: NSString = (textField.text ?? "") as NSString
let txtAfterUpdate = textFieldText.replacingCharacters(in: range, with: string)
if(newLength <= 15){
var currentPosition = 0
if let selectedRange = textField.selectedTextRange {
currentPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start)
}
if(string == ""){
if(currentPosition == 2){
if(textField.text!.count > 2){
currentPosition = 1
}else{
currentPosition = 0
}
}else if(currentPosition == 7){
currentPosition = 4
}else if(currentPosition == 11){
currentPosition = 9
}else if(currentPosition == 14){
currentPosition = 12
}else{
if(currentPosition != 1){
currentPosition = currentPosition - 1
}
}
}else{
if(currentPosition == 0){
currentPosition = 2
}else if(currentPosition == 4){
currentPosition = 7
}else if(currentPosition == 9){
currentPosition = 11
}else if(currentPosition == 12){
currentPosition = 14
}else{
currentPosition = currentPosition + 1
}
}
textField.text = txtAfterUpdate.applyPatternOnNumbers()
print("textField Length -> : \(textField.text?.count ?? 0)")
if let newPosition = textField.position(from: textField.beginningOfDocument, offset: currentPosition) {
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
}
return false
}
return newLength <= 15
}
return true
}
Related
I'm trying to autoformat my textfield in the format XXX-XXX-XXXX. The rules are that it should be in the format as mentioned and the first number should be greater than zero and should be of max 10 digits, the regex for this is already added in my function. Below are the methods I'm using
#IBAction func validateAction(_ sender: Any) {
guard let phoneNumber = phoneNumber.text else {return }
if validatePhoneNumber(phoneNumber: phoneNumber) {
errorMessage.text = "Validation successful"
} else {
errorMessage.text = "Validation failed"
}
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let currentText = textField.text as NSString? else {return true}
let textString = currentText.replacingCharacters(in: range, with: string)
if textField == phoneNumber {
return textField.updatePhoneNumber(string, textString)
}else{
return true
}
}
func validatePhoneNumber(phoneNumber: String) -> Bool {
let phoneRegex: String = "^[2-9]\\d{2}-\\d{3}-\\d{4}$"
return NSPredicate(format: "SELF MATCHES %#", phoneRegex).evaluate(with: phoneNumber)
}
extension UITextField {
func updatePhoneNumber(_ replacementString: String?, _ textString: String?) -> Bool {
guard let textCount = textString?.count else {return true}
guard let currentString = self.text else {return true}
if replacementString == "" {
return true
} else if textCount == 4 {
self.text = currentString + "-"
} else if textCount == 8 {
self.text = currentString + "-"
} else if textCount > 12 || replacementString == " " {
return false
}
return true
}
}
This works to some extent, now the issue is, user can manually intervene and disrupt the format for eg: if I entered, 234-567-8990, user can place the cursor just before 5 and backspace and type in at the end or between like 567-89900000 or 234567-8990. By validating the regular expression it will give an error but I want to re-adjust the format as user types in. For eg: in the earlier scenario if the user is on cursor before 5 and backspaces it should not remove the dash (-) but just removes 4 and re-adjust format like 235-678-990. Is there any simple way to do this? Any help is appreciated
I use this extension for String. It's small and real helpful.
extension String {
func applyPatternOnNumbers(pattern: String, replacmentCharacter: Character) -> String {
var pureNumber = self.replacingOccurrences( of: "[^0-9]", with: "", options: .regularExpression)
for index in 0 ..< pattern.count {
guard index < pureNumber.count else { return pureNumber }
let stringIndex = String.Index(encodedOffset: index)
let patternCharacter = pattern[stringIndex]
guard patternCharacter != replacmentCharacter else { continue }
pureNumber.insert(patternCharacter, at: stringIndex)
}
return pureNumber
}
just set a needed mask
text.applyPatternOnNumbers(pattern: "+# (###) ###-##-##", replacmentCharacter: "#")
and that's all
#SonuP very good question. I believe you want to format the phone and also keep the cursor in correct position. If so, then this task is slightly more complex than just formatting. You need to reformat the code and update the cursor position.
Note that my solution follows the specific formatting and if it does not match yours, then tweak the code slightly:
Swift 5
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
var text = textField.text ?? ""
text.replaceSubrange(range.toRange(string: text), with: string)
if let phone = (textField.text ?? "").replacePhoneSubrange(range, with: string) {
// update text in the field
textField.text = text
// update cursor position
if text.count == range.location + string.count || text.hasSuffix(")") && text.count == range.location + string.count + 1 { // end
if phone.hasSuffix(")") {
textField.setCursor(phone.count - 1)
}
else {
textField.setCursor(phone.count)
}
}
else {
textField.setCursor(min(range.location + string.count, phone.count-1))
}
}
return false
}
Also you will need the following extensions:
// MARK: - Helpful methods
extension NSRange {
/// Convert to Range for given string
///
/// - Parameter string: the string
/// - Returns: range
func toRange(string: String) -> Range<String.Index> {
let range = string.index(string.startIndex, offsetBy: self.lowerBound)..<string.index(string.startIndex, offsetBy: self.upperBound)
return range
}
static func fromRange(_ range: Range<String.Index>, inString string: String) -> NSRange {
let s = string.distance(from: string.startIndex, to: range.lowerBound)
let e = string.distance(from: string.startIndex, to: range.upperBound)
return NSMakeRange(s, e-s)
}
}
// MARK: - Helpful methods
extension String {
/// Raplace string in phone
public func replacePhoneSubrange(_ range: NSRange, with string: String) -> String? {
if let phone = self.phone { // +11-111-111-1111 (111)
var numberString = phone.phoneNumber // 111111111111111
let newRange = self.toPhoneRange(range: range)
numberString.replaceSubrange(newRange.toRange(string: phone), with: string)
return numberString.phone
}
return nil
}
/// Phone number string
public var phoneNumber: String {
let components = self.components(
separatedBy: CharacterSet.decimalDigits.inverted)
var decimalString = NSString(string: components.joined(separator: ""))
while decimalString.hasPrefix("0") {
decimalString = decimalString.substring(from: 1) as NSString
}
return String(decimalString)
}
/// Get phone range
public func toPhoneRange(range: NSRange) -> NSRange {
let start = range.location
let end = start + range.length
let s2 = self.convertPhoneLocation(location: start)
let e2 = self.convertPhoneLocation(location: end)
return NSRange(location: s2, length: e2-s2)
}
/// Get cursor location for phone
public func convertPhoneLocation(location: Int) -> Int {
let substring = self[self.startIndex..<self.index(self.startIndex, offsetBy: location)]
return String(substring).phoneNumber.count
}
}
// MARK: - Helpful methods
extension UITextField {
/// Set cursor
///
/// - Parameter position: the position to set
func setCursor(_ position: Int) {
if let startPosition = self.position(from: self.beginningOfDocument, offset: position) {
let endPosition = startPosition
self.selectedTextRange = self.textRange(from: startPosition, to: endPosition)
}
}
}
// MARK: - Helpful methods
extension String {
/// phone formatting
public var phone: String? {
let components = self.components(
separatedBy: CharacterSet.decimalDigits.inverted)
var decimalString = NSString(string: components.joined(separator: ""))
while decimalString.hasPrefix("0") {
decimalString = decimalString.substring(from: 1) as NSString
}
let length = decimalString.length
let hasLeadingOne = length > 0 && length == 11
let hasLeadingTwo = length > 11
if length > 15 {
return nil
}
var index = 0 as Int
let formattedString = NSMutableString()
if hasLeadingOne || hasLeadingTwo {
let len = hasLeadingTwo ? 2 : 1
let areaCode = decimalString.substring(with: NSMakeRange(index, len))
formattedString.appendFormat("+%#-", areaCode)
index += len
}
if (length - index) > 3 {
let areaCode = decimalString.substring(with: NSMakeRange(index, 3))
formattedString.appendFormat("%#-", areaCode)
index += 3
}
if length - index == 4 && length == 7 { // xxx-xxxx
let prefix = decimalString.substring(with: NSMakeRange(index, 4))
formattedString.append(prefix)
index += 4
}
else if length - index > 3 {// xxx-xxx-x...
let prefix = decimalString.substring(with: NSMakeRange(index, 3))
formattedString.appendFormat("%#-", prefix)
index += 3
}
if length - index == 4 { // xxx-xxx-xxxx
let prefix = decimalString.substring(with: NSMakeRange(index, 4))
formattedString.append(prefix)
index += 4
}
// format phone extenstion
if length - index > 4 {
let prefix = decimalString.substring(with: NSMakeRange(index, 4))
formattedString.appendFormat("%# ", prefix)
index += 4
}
let remainder = decimalString.substring(from: index)
if length > 12 {
formattedString.append("(\(remainder))")
}
else {
formattedString.append(remainder)
}
return (formattedString as String).trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines)
}
}
Use this in textfield delegate method :
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if range.length > 0 {
return true
}
if string == "" {
return false
}
if range.location > 11 {
return false
}
var originalText = textField.text
let replacementText = string.replacingOccurrences(of: " ", with: "")
if !CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: replacementText)) {
return false
}
if range.location == 3 || range.location == 7 {
originalText?.append("-")
textField.text = originalText
}
return true
}
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.
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
}
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
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
}
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
}
I have a textfield and I do not want users to be able to set the cursor position by touching and holding at the textfield. Is there a way to always have the cursor to be at the very end of the textfield?
First of all, its not good to change this type of default behavior of textField.
As per your comment if you want to add credit card and you are facing some input complexity then I found code from my old project and might be it will work for you.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let replacementStringIsLegal = string.rangeOfCharacter(from: NSCharacterSet(charactersIn: "0123456789").inverted) == nil
if !replacementStringIsLegal {
return false
}
let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
let components = newString.components(separatedBy: NSCharacterSet(charactersIn: "0123456789").inverted)
let decimalString = components.joined(separator: "") as NSString
let length = decimalString.length
let hasLeadingOne = length > 0 && decimalString.character(at: 0) == (1 as unichar)
if length == 0 || (length > 16 && !hasLeadingOne) || length > 19
{
let newLength = (textField.text! as NSString).length + (string as NSString).length - range.length as Int
return (newLength > 16) ? false : true
}
var index = 0 as Int
let formattedString = NSMutableString()
if hasLeadingOne
{
formattedString.append("1 ")
index += 1
}
if length - index > 4
{
let prefix = decimalString.substring(with: NSMakeRange(index, 4))
formattedString.appendFormat("%# ", prefix)
index += 4
}
if length - index > 4
{
let prefix = decimalString.substring(with: NSMakeRange(index, 4))
formattedString.appendFormat("%# ", prefix)
index += 4
}
if length - index > 4
{
let prefix = decimalString.substring(with: NSMakeRange(index, 4))
formattedString.appendFormat("%# ", prefix)
index += 4
}
let remainder = decimalString.substring(from: index)
formattedString.append(remainder)
textField.text = formattedString as String
return false
}
I have created a UITextfield where i want to add 4 digit password, but once I enter the first digit whole placeholder disappear. how can I keep next three placeholder letters in UITextfield while entering next password letters.
here is my screenshot:
I wanted to try SeanLintern88's solution because it sounded like a little challange. And it is in the case where the text field should have spaces between the underscore.
textField.text = "_ _ _ _"
This is the solution I came with and while it was fun to write, this is something I do not recommend using in real projects. Better try the 4 separate text fields approach :)
extension ViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else { return false }
var location = range.location
//is deleting
if string == "" {
guard let indexToReplace = text.index(text.startIndex, offsetBy: location, limitedBy: text.endIndex) else {
return false
}
let isCharDeleted = location % 2 == 0
//place " " or "_" depending on the position that was deleted
let stringToReplaceWith = isCharDeleted ? "_" : " "
let charachter = stringToReplaceWith[stringToReplaceWith.startIndex]
textField.text?.remove(at: indexToReplace)
textField.text?.insert(charachter, at: indexToReplace)
var newCursorPositionOffset = location
//deletetion occured on space " "
if !isCharDeleted {
guard let previousIndex = text.index(text.startIndex, offsetBy: location-1, limitedBy: text.endIndex) else {
return false
}
//delete the previous charachter
textField.text?.remove(at: previousIndex)
let dash = "_"
let char = dash[dash.startIndex]
textField.text?.insert(char, at: previousIndex)
//correct cursor position
newCursorPositionOffset -= 1
}
//move cursor position
let newPosition = textField.position(from: textField.beginningOfDocument, offset: newCursorPositionOffset)
textField.selectedTextRange = textField.textRange(from: newPosition!, to: newPosition!)
return false
}
//is typing
if range.location + 1 <= text.characters.count,
let end = text.index(text.startIndex, offsetBy: location+1, limitedBy: text.endIndex),
let start = text.index(text.startIndex, offsetBy: location, limitedBy: text.endIndex) {
textField.text = textField.text?.replacingOccurrences(of: "_", with: string, options: .caseInsensitive, range: Range(uncheckedBounds: (lower: start, upper: end)))
//correct the cursor position if placed on " " index
if range.location % 2 != 0 {
location -= 1
}
}
//skip " " and move cursor to the next "_"
if location+2 < text.characters.count {
let newPosition = textField.position(from: textField.beginningOfDocument, offset: location+2)
textField.selectedTextRange = textField.textRange(from: newPosition!, to: newPosition!)
}
return false
}
func textFieldDidBeginEditing(_ textField: UITextField) {
let newPosition = textField.beginningOfDocument
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
}
}
PS: Probably it can be made shorter with better choosing of functions for string operations, but still a pretty .. unfriendly solution.
Conclusion: DON'T DO THIS AT HOME :D
Instead of using placeHolder, just override the shouldChangeCharactersInRange method and append the characters to the string until the string is 4 characters long, you can also use attributed string if you want the _ to look different to the dots.
Swift 4
This is a modified version of #Denislava Shentova's answer that I believe simplifies into less lines of code, fixes issues, and makes the code more readable.
Not Fully Tested
import UIKit
class YourClass: UIViewController {
//It is also a good idea to deny users the ability to paste into this textField.
//set up textField
let textField : UITextField = {
let textField = UITextField()
// These are 'long dashes' you can replace them with whatever you would like.
// These look best IMO.
textField.text = "——————" //No spaces needed!
textField.textColor = .black
textField.textAlignment = .center
textField.tintColor = .clear //this will hide the cursor.
return textField
}()
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
//This sets the spacing or 'Kern' of the textfield. Adjust the value: 10.0 and the fontSize to get the desired output.
textField.defaultTextAttributes.updateValue(10.0, forKey: NSAttributedStringKey.kern.rawValue)
}
}
extension YourClass : UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
//get the current text of the textField.
guard let text = textField.text else { return false }
//handle backspace event.
if string == "" {
guard let indexToReplace = text.index(text.startIndex, offsetBy: range.location, limitedBy: text.endIndex) else { return false }
textField.text?.remove(at: indexToReplace)
textField.text?.insert("—", at: indexToReplace)
//adjust cursor position
if let newPostion = textField.position(from: textField.beginningOfDocument, offset: range.location) {
textField.selectedTextRange = textField.textRange(from: newPostion, to: newPostion)
return false
}
}
//handle character entered event.
if range.location + 1 <= text.count,
let end = text.index(text.startIndex, offsetBy: range.location + 1, limitedBy: text.endIndex),
let start = text.index(text.startIndex, offsetBy: range.location, limitedBy: text.endIndex) {
textField.text = textField.text?.replacingOccurrences(of: "—", with: string, options: .caseInsensitive, range: Range(uncheckedBounds: (lower: start, upper: end)))
}
//adjust cursor position.
if range.location + 1 < text.count {
if let newPosition = textField.position(from: textField.beginningOfDocument, offset: range.location + 1){
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
}
}
return false
}
//make sure to start at the begining of the textField.
func textFieldDidBeginEditing(_ textField: UITextField) {
let newPosition = textField.beginningOfDocument
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
}
}
So I want to have a UITextField to only accept digits, solved that by using a custom keyboard input.
The intention of this UITextField is to get someones birthday. I don't want to use an UIDatePicker tough as I don't like it's appearance.
I'd like that the TextField automatically inserts dashes after every second digit that the user put into the TextField.
dd-mm-yy is the placeholder text. I either thought of making the dashes permanently but I don't know how to do that either.
How can I do this?
You want to allow user to enter text in textfield in this dd-mm-yy right ?
if it so i'am sure this will help you.
In top of your class declare this variable which we gonna use later.
var dateFormate = Bool()
Add delegate and tag for that textfield.
Then add this following delegate method
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
//1. To make sure that this is applicable to only particular textfield add tag.
if textField.tag == 1 {
//2. this one helps to make sure that user enters only numeric characters and '-' in fields
let numbersOnly = NSCharacterSet(charactersInString: "1234567890-")
let characterSetFromTextField = NSCharacterSet(charactersInString: string)
let Validate:Bool = numbersOnly .isSupersetOfSet(characterSetFromTextField)
if !Validate {
return false;
}
if range.length + range.location > textField.text?.characters.count {
return false
}
let newLength = (textField.text?.characters.count)! + string.characters.count - range.length
if newLength == 3 || newLength == 6 {
let char = string.cStringUsingEncoding(NSUTF8StringEncoding)!
let isBackSpace = strcmp(char, "\\b")
if (isBackSpace == -92) {
dateFormate = false;
}else{
dateFormate = true;
}
if dateFormate {
let textContent:String!
textContent = textField.text
//3.Here we add '-' on overself.
let textWithHifen:NSString = "\(textContent)-"
textField.text = textWithHifen as String
dateFormate = false
}
}
//4. this one helps to make sure only 8 character is added in textfield .(ie: dd-mm-yy)
return newLength <= 8;
}
return true
}
That's it now user can enter their DOB.No need to worry about '-' it will be added automatically.
Swift 3:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
//1. To make sure that this is applicable to only particular textfield add tag.
if textField.tag == 1 {
//2. this one helps to make sure that user enters only numeric characters and '-' in fields
let numbersOnly = CharacterSet(charactersIn: "1234567890-")
let Validate = string.rangeOfCharacter(from: numbersOnly.inverted) == nil ? true : false
if !Validate {
return false;
}
if range.length + range.location > textField.text?.characters.count {
return false
}
let newLength = (textField.text?.characters.count)! + string.characters.count - range.length
if newLength == 3 || newLength == 6 {
let char = string.cString(using: NSUTF8StringEncoding)!
let isBackSpace = strcmp(char, "\\b")
if (isBackSpace == -92) {
dateFormate = false;
}else{
dateFormate = true;
}
if dateFormate {
let textContent:String!
textContent = textField.text
//3.Here we add '-' on overself.
let textWithHifen:NSString = "\(textContent)-"
textField.text = textWithHifen as String
dateFormate = false
}
}
//4. this one helps to make sure only 8 character is added in textfield .(ie: dd-mm-yy)
return newLength <= 8;
}
return true
}
Swift5
// Use textfield delegate shouldChangeCharactersIn
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if (textField.text?.count == 2) || (textField.text?.count == 5) {
if !(string == "") {
textField.text = (textField.text)! + "-"
}
}
return !(textField.text!.count > 7 && (string.count ) > range.length)
}