How to Masking the Last Number in Swift

How to masking the last number in Swift?

Use a prefix instead of a suffix

extension StringProtocol {
var masked: String {
return prefix(5) + String(repeating: "•", count: Swift.max(0, count-5))
}
}

You could also create a function instead for parameterizing the number of digits and direction (or even the mask character)

extension StringProtocol {
func masked(_ n: Int = 5, reversed: Bool = false) -> String {
let mask = String(repeating: "•", count: Swift.max(0, count-n))
return reversed ? mask + suffix(n) : prefix(n) + mask
}
}

var name = "0123456789"

print(name.masked(5))
// 01234•••••

print(name.masked(5, reversed: true))
// •••••56789

Card Number Masking

Your question contains 2 important parts:

A regex that matches all characters but first 6 and last 2

let regexPattern = "(?<=.{6}).(?=.*.{2}$)"

and

An extension on the String that takes the regex and masks it:

extension String {

func masked(matching regexPattern: String, with template: String = "*") throws -> String {
let regex = try NSRegularExpression(pattern: regexPattern, options: NSRegularExpression.Options.caseInsensitive)
let range = NSMakeRange(0, count)
return regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: template)
}
}

Usage:

let cardNumber = "5890040000000016"
let regexPattern = "(?<=.{6}).(?=.*.{2}$)"

print("Output:", try! cardNumber.masked(matching: regexPattern))

Output: 589004********16

How to mask a String to show only the last 3 characters?

This does exactly what you want:

let name = "0123456789"
let conditionIndex = name.characters.count - 3
let maskedName = String(name.characters.enumerated().map { (index, element) -> Character in
return index < conditionIndex ? "x" : element
})
print("Masked Name: ", maskedName) // xxxxxxx789

What happens here is that you get an array of the characters of the string using enumerated() method, then map each character to a value based on a condition:

  • If the index of the character is less than condtionIndex we replace the character with an x (the mask).
  • Else, we just leave the character as is.

How to masking textfield in Swift 4?

func hide(email: String) -> String {

let parts = email.split(separator: "@")
if parts.count < 2 {
return email
}
let name = parts[0]
let appendix = parts[1]
let lenght = name.count
if lenght == 1 {
return "*@\(appendix)"
}
let semiLenght = lenght / 2

var suffixSemiLenght = semiLenght
if (lenght % 2 == 1) {
suffixSemiLenght += 1
}

let prefix = String(repeating: "*", count: semiLenght)
let lastPart = String(name.suffix(suffixSemiLenght))

let result = "\(prefix)\(lastPart)@\(appendix)"
return result
}
let email = "123456789@gmail.com"
let result = hide(email: email)
print(result)

Masking email and phone number in Swift 4

Basically, you could use a function like this. It hides all chars despite the leading and trailing two chars:

func hideMidChars(_ value: String) -> String {
return String(value.enumerated().map { index, char in
return [0, 1, value.count - 1, value.count - 2].contains(index) ? char : "*"
})
}

Please note there's currently no special handling done for very short input strings.

Using this function for the phone number should be trivial; as for the email, if you only want to hide the first part, you could use the following code:

let email = "123456@test.com"
let components = email.components(separatedBy: "@")
let result = hideMidChars(components.first!) + "@" + components.last!

The result constant will be 12**56@test.com.

This of course assumes that the email is in a valid format, otherwise force unwrapping the first and last array component could crash. However, handling this would be out of scope for this question.

How can i mask the first and last characters in Swift?

Pretty simple, really. You just need to reverse the order of the characters from the string and the mask in the "not lastCharacters" case:

extension String {
func maskedChar(_ charCount: Int, lastCharacters: Bool = true) -> String {
if self.count < charCount {
return String(repeating: "*", count: self.count)
}
let mask = String(repeating: "*", count: charCount)
if lastCharacters {
return self.prefix(self.count - charCount) + mask
} else {
return mask + self.suffix(self.count - charCount)
}
}
}

Note that I also changed the if clause at the beginning. It seems to me you should ALWAYS mask the data, even if the source string is too short.

Masking First and Last Name String with *

You could e.g. use pattern matching for lower-case characters and replace those that match the pattern with asterisk characters (*):

let name = "Johnny Tuck"
let pattern = Character("a")..."z"
let maskedName = String(name.characters.map { pattern ~= $0 ? Character("*") : $0 })
print(maskedName) // J***** T***

If the purpose is not to replace lower case characters by * but rather to mask all characters that are not the first of a given word (for, say, a specific separator " "), you could separate the String name by a separator, and apply a masking to all but the initial character for all separated words (sub-names), follwed by finally reconstruct the masked string:

import Foundation
let name = "johnny lucky tuck"
let maskedName = name.components(separatedBy: " ")
.filter { !$0.isEmpty }.map { $0.characters }
.map { String($0.first!).uppercased() + String(repeating: "*", count: $0.dropFirst(1).count) }
.joined(separator: " ")
print(maskedName) // J***** L**** T***

Note the uppercased() above, which sets the initial non-masked letter to a uppercased one (even if it is not initially). If you do not wish this uppercasing, simply remove the .uppercased() call above.

Masking characters in a Swift string

Use replacingOccurrences with options:

let str = "abcdba"

let result = str.replacingOccurrences(of: "[^ab]", with: "", options: .regularExpression)

print(result) //"abba"

Or you could define a function like this:

func maskString (
_ str: String,
withMask mask: String ,
replaceWith replacement: String = ""
) -> String {
return str
.replacingOccurrences(of: "[^\(mask)]",
with: replacement,
options: .regularExpression)
}

And use it like so:

maskString("abcdba", withMask: "ab")                    //"abba"
maskString("abcdba", withMask: "ab" , replaceWith: "?") //"ab??ba"

Mask textField in swift

This way you can create a telephone mask in Swift.

First create a nifty extension for the String type. The subscript gets the character at an index and the function gets a String.Index type from an int!.

extension String {  
subscript (i: Int) -> String {

if countElements(self) > i {

return String(Array(self)[i])
}

return ""
}

func indexAt(theInt:Int)->String.Index {

return advance(self.startIndex, theInt)
}
}

And this is the function to call on the text in your phone number entry field:

func returnMaskedPhoneField(thePhoneText:String)->String{

var returnString = thePhoneText

//Trims non-numerical characters
returnString = returnString.stringByTrimmingCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet)
//Removes all spaces
returnString = returnString.stringByReplacingOccurrencesOfString(" ", withString: "")

//Checks if we need to format a mobile number
if thePhoneText[1] == "4"{

if countElements(returnString) > 7 {

returnString = returnString.stringByReplacingCharactersInRange(Range<String.Index>(start: returnString.indexAt(7), end: returnString.indexAt(7)), withString: " ")

}

if countElements(returnString) > 4 {

returnString = returnString.stringByReplacingCharactersInRange(Range<String.Index>(start: returnString.indexAt(4), end: returnString.indexAt(4)), withString: " ")
}

}else {

if countElements(returnString) > 6 {

returnString = returnString.stringByReplacingCharactersInRange(Range<String.Index>(start: returnString.indexAt(6), end: returnString.indexAt(6)), withString: " ")

}

if countElements(returnString) > 2 {

returnString = returnString.stringByReplacingCharactersInRange(Range<String.Index>(start: returnString.indexAt(2), end: returnString.indexAt(2)), withString: " ")
}

}

return returnString
}

Then then here is where you would implement the function, put this in your viewDidLoad method:

aTextField.delegate = self  
aTextField.addTarget(self, action: "validateTextFields:", forControlEvents: UIControlEvents.EditingChanged)

And this one somewhere in the class that's your textfield delegate:

func validateTextFields(sender:AnyObject){

if let textField = sender as? UITextField {

if textField == aTextField {

if let currentCurserPosition = aTextField?.selectedTextRange {

var isEndOfString = false

let currentCurserPositionInteger = textField.offsetFromPosition(textField.beginningOfDocument, toPosition: currentCurserPosition.start)

if currentCurserPositionInteger == count(textField.text){

isEndOfString = true
}

aTextField?.text = returnMaskedPhoneField(textField.text)

if isEndOfString == false {
aTextField?.selectedTextRange = currentCurserPosition
}

}else {

aTextField?.text = returnMaskedPhoneField(textField.text)
}
}
}
}

And it will work like:

Sample Image

Credits:

http://pjeremymalouf.com/creating-a-text-mask-in-swift/

And if you want to use custom textField then you can use AKMaskField.

Where you can find textField for phone like this:

Sample Image



Related Topics



Leave a reply



Submit