How to check in Swift if a Regular Expression is valid? - ios

I'm using Regex to search in a textView. All works fine with simple strings but when I try to enter only a part of a regular expression operator I get a cash with the error:
Error Domain=NSCocoaErrorDomain Code=2048 "The value “\” is invalid." UserInfo={NSInvalidValue=\}
For example if I enter "\n" it works, but if I enter only "\" (without quotes), I get the crash. What I can't get to do is to find a way to check the expression before to use it.
I'm using this code partially based on this tutorial and this answer by Wiktor Stribiżew:
extension NSRegularExpression {
convenience init?(options: SearchOptions) {
let searchString = options.searchString
let isCaseSensitive = options.matchCase // set to true
let isWholeWords = options.wholeWords // set to false
let escapeMetacharacters = options.escapeMetacharacters // set to false
// handle case sensitive option
var regexOption: NSRegularExpressionOptions = .CaseInsensitive
if isCaseSensitive { // if it is match case remove case sensitive option
regexOption = []
}
// put the search string in the pattern
var pattern = searchString
if isWholeWords {
pattern = "(?<!\\w)" + NSRegularExpression.escapedPatternForString(searchString) + "(?!\\w)"
}
do {
try self.init(pattern: pattern, options: regexOption)
} catch {
print(error)
}
}
}

The first code below have shown unstable behaviour and you should not use it.
(Please see the latter part of this answer.)
Add one line to your failable initializer:
do {
try self.init(pattern: pattern, options: regexOption)
} catch {
print(error)
return nil //->you need to return nil to tell initialization failed
}
(I think Swift compiler should warn about this missing return nil. May be a bug of Swift?)
After that you can safely check the result if it's nil or not:
let sOpts = SearchOptions(searchString: "\\", replacementString: "", matchCase: false, wholeWords: false)
if let regex = NSRegularExpression(options: sOpts) {
//Use regex
print(regex)
} else {
//Process errors
print("Something bad in SearchOptions")
}
(I omitted escapeMetacharacters, as it's not used yet.)
As far as I tested, using static method has never crashed.
extension NSRegularExpression {
static func expresssionWith(options: SearchOptions) -> NSRegularExpression? {
let searchString = options.searchString
let isCaseSensitive = options.matchCase // set to true
let isWholeWords = options.wholeWords // set to false
// handle case sensitive option
var regexOption: NSRegularExpressionOptions = .CaseInsensitive
if isCaseSensitive { // if it is match case remove case sensitive option
regexOption = []
}
// put the search string in the pattern
var pattern = searchString
if isWholeWords {
pattern = "(?<!\\w)" + NSRegularExpression.escapedPatternForString(searchString) + "(?!\\w)"
}
do {
return try NSRegularExpression(pattern: pattern, options: regexOption)
} catch {
print(error)
return nil
}
}
}
let sOpts = SearchOptions(searchString: "\\", replacementString: "", matchCase: false, wholeWords: false)
if let regex = NSRegularExpression.expresssionWith(sOpts) {
//Use regex
print(regex)
} else {
//Process errors
print("Something bad in SearchOptions")
}

Related

Swift - Assign newValue to an Object

I know that probably is a very simple question, however I spent a lot of time trying to figure out why is not working, and still doesn't make sense for me, so I need help.
I am learning iOS, I came from Android where I am used to work with objects.
I want to do something similar that I have been doing with Android(maybe this is the problem).
I have created an object with the methods get and set.
private var _token: String!
var error: String {
get {
guard self._error != nil else { return "" }
return _error
}
set {
self._token = newValue
}
}
When I want to manipulate this object, is when I am having the problem.
let objectCreated = ObjectCreated()
guard let errorReceived = (xml["Whatever"]["Whatever"].element?.text) else { return }
print(errorReceived)
objectCreated.error = errorReceived
print(objectCreated.error)
The first print is printing the correct String, but the second is printing "". So the set method is not doing his job.
Isn't it supposed to be
...
guard self._token != nil else { return "" }
return _token
...
This can be simplified with the nil-coalescing operator
var error: String {
get {
return self._token ?? ""
}
set {
self._token = newValue
}
}
Note: Variable names with leading underscores are unusual in Swift.
private var _error: String!
var error: String {
get {
guard self._error != nil else { return "" }
return _error
}
set {
self._error = newValue
}
}
self._token = newValue >>>> self._error = newValue

How to validate an email that it should contain at least some characters before "#"

in my app user can enter his email or phone number. I need to validate wether it's a phone number or email. if email entered it should be validated
ex: if user entered only "#mail.com" need to show not a valid mail to user.there should be at least 2 or three characters front of "#" here is my code
func validateEmail(enteredEmail:String) -> Bool {
let emailFormat = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPredicate = NSPredicate(format:"SELF MATCHES %#", emailFormat)
let email = emailPredicate.evaluate(with: enteredEmail)
if enteredEmail.contains("#") {
let characters = enteredEmail.components(separatedBy: "#")
if characters.count > 0 {
if characters[0].isEmpty {
return false
} else {
return true
}
}
}
return email ? email : enteredEmail.count == 10 //if email evaluation is false check for phone number count
}
This code is working fine for me but need a better solution. Thanks in advance
Why don't you simply modify the regex? It already checks if there is one or more characters before the # character. If you want to check for two or more use {2,}
let emailFormat = "[A-Z0-9a-z._%+-]{2,}#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
Apart from the phone validation this is a swiftier way to apply the regex
The pattern is
2 or more characters from the character set [A-Z0-9a-z._%+-]
one #
one or more characters from the character set [A-Za-z0-9.-]
one .
2-64 upper- or lowercase alpha letters
func validateEmail(enteredEmail:String) -> Bool {
let emailFormat = "[A-Z0-9a-z._%+-]{2,}#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
return enteredEmail.range(of: emailFormat, options: .regularExpression) != nil
}
If the entered string must exactly match the pattern use
let emailFormat = "^[A-Z0-9a-z._%+-]{2,}#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}$"
Edit:
To include also the phone validation (just 10 digits) use
func validateEmail(enteredEmail:String) -> Bool {
let emailFormat = "^[A-Z0-9a-z._%+-]{2,}#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}$"
guard enteredEmail.range(of: emailFormat, options: .regularExpression) == nil else { return true }
return enteredEmail.range(of: "^\\d{10}$", options: .regularExpression) != nil
}
use hasPrefix:
Example:
"hello dolly".hasPrefix("hello") // This will return true
"hello dolly".hasPrefix("abc") // This will return false
That way you can check if the first character is '#' or not and go on from there with an if-else statement.
Try This :
class func isValidEmail(testStr:String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
let emailTest = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailTest.evaluate(with: testStr)
}
the function is defined properly the issue that will be faced is when user type email like " #mail.com" as you are not trimming characters before validation.
Your code should be as follows:
if enteredEmail.contains("#")
{
let characters = enteredEmail.trimmingCharacters(in: CharacterSet.whitespaces).components(separatedBy: "#")
if characters.count > 0 {
if characters[0] > 2 {
return true
}else {
return false
}
}
}
The regex is fine: the error is in the return statement -and I actually don't like the code in the middle of the method-. You should validate phone numbers with another regex, not just string length, and then drop that if.
Here you have a cleaner example. You should change the phone number regex: it's for Spanish phone numbers.
import Foundation
func validateEmail(enteredEmail:String) -> Bool {
let emailFormat = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPredicate = NSPredicate(format:"SELF MATCHES %#", emailFormat)
let email = emailPredicate.evaluate(with: enteredEmail)
return email
}
func validatePhoneNumber(enteredPhoneNumber:String) -> Bool {
let phoneFormat = "\\A[0-9]{9}\\z"
let phonePredicate = NSPredicate(format:"SELF MATCHES %#", phoneFormat)
let phone = phonePredicate.evaluate(with: enteredPhoneNumber)
return phone
}
func validate(enteredString: String) -> Bool {
if validateEmail(enteredEmail: enteredString) == true {
return true
}
else {
return validatePhoneNumber(enteredPhoneNumber: enteredString)
}
}
validate(enteredString: "#email.com") // false
validate(enteredString: "some#email.com") // true: first regex
validate(enteredString: "666666666") // true: second regex
validate(enteredString: "some rubbish") // false

Swift: make debugging easier by being able to catch return value in defer statement

So I love declaring variables to hold return value and then return said variable on next line, thus making it easy to debug my code, I can just set a breakpoint at the return line and see what value it returns. I use this everywhere and it makes all my code so much easier to debug.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let cellCount = models.count
return cellCount
}
But then you have the scenario where you have optionals and different conditions that have to be met in order for your method to makes sense. The guard statement is great for making sure some conditions are met, while not introducing pyramids of doom.
But the problem with early returns is that you get at least two exit points (because guard requires a return in this context) from your method, which makes it harder to debug.
// Instantiate using dependency injection
private let reachability: ReachabilityProtocol
private let apiClient: APIClientProtocol
// Returns true if could start login request, else false
func loginUser(username: String, password: String) -> Bool {
defer {
// Not possible, would be nice! Return value would be an implicitly declared variable
// exaclty like the variables 'newValue' and 'oldValue' in property observers!
print("return value: \(returnValue)")
}
guard reachability.isOnline && !username.isEmpty && !password.isEmpty { return false }
apiClient.loginUser(username, password: password)
return true
}
It would be awesome if Swift 3.X would make the defer statement able to catch the return value, wouldn't it?
This would make debugging so much easier, whilst still making use of guard and early returns. I have not insight what so ever in writing compilers etc, but it feels like this would not be so hard to implement in coming versions of Swift?
Can you come up with a different way of achieving a single point to read return value of a method with multiple exit points? (Without having to wait for my suggested improvement to defer?)
Edit:
My example above with the login is not a perfect example, sorry, why would I write code like that? Haha! But there are many other similar scenarios, maybe something like this, using do-try-catch also makes code hard to debug:
// We don't know the return value of this function! Makes it hard to debug!
func fetchUserByFirstName(firstName: String, andLastName lastName: String, fromContext context: NSManagedObjectContext) -> User? {
defer {
// Not possible, would be nice! Return value would be an implicitly declared variable
// exaclty like the variables 'newValue' and 'oldValue' in property observers!
print("return value: \(returnValue)")
}
guard !firstName.isEmpty else { print("firstName can't be empty"); return nil }
guard !lastName.isEmpty else { print("lastName can't be empty"); return nil }
// Imagine we have some kind of debug user... Does not really make sense, but good for making a point.
guard firstName != "DEBUG" else { return User.debugUser }
let fetchRequest = NSFetchRequest(entityName: Users.entityName)
let predicate = NSPredicate(format: "firstName == \(firstName) AND lastName == \(lastName)")
fetchRequest.predicate = predicate
do {
let user = try context.executeFetchRequest(fetchRequest)
return user
} catch let error as NSError {
print("Error fetching user: \(error)")
}
return nil
}
I like your suggested improvement to Swift to have defer capture the return value.
Here is something that will work, but it isn't perfect because it requires a little extra work (and code clutter), but you can do it manually by declaring returnValue with let at the top of your function, giving it the same type that the function returns. Then, replace all of your return <something> with returnValue = <something>; return returnValue.
By declaring returnValue with let, Swift will let you know if you forget to assign returnValue before leaving the function. So if you add a new return to your function, your function won't compile until you assign the returnValue. You'll see the error: error: constant 'returnValue' used before being initialized.
func fetchUserByFirstName(firstName: String, andLastName lastName: String, fromContext context: NSManagedObjectContext) -> User? {
let returnValue: User?
defer {
print("return value: \(returnValue)")
}
guard !firstName.isEmpty else { print("firstName can't be empty"); returnValue = nil; return returnValue }
guard !lastName.isEmpty else { print("lastName can't be empty"); returnValue = nil; return returnValue }
// Imagine we have some kind of debug user... Does not really make sense, but good for making a point.
guard firstName != "DEBUG" else { returnValue = User.debugUser; return returnValue }
let fetchRequest = NSFetchRequest(entityName: Users.entityName)
let predicate = NSPredicate(format: "firstName == \(firstName) AND lastName == \(lastName)")
fetchRequest.predicate = predicate
do {
let user = try context.executeFetchRequest(fetchRequest)
returnValue = user; return returnValue
} catch let error as NSError {
print("Error fetching user: \(error)")
}
returnValue = nil; return returnValue
}
Alternatively (just brainstorming here...), put your function that has multiple exit points into an inner function, and then call it:
func fetchUserByFirstName(firstName: String, andLastName lastName: String, fromContext context: NSManagedObjectContext) -> User? {
func innerFunc(firstName: String, andLastName lastName: String, fromContext context: NSManagedObjectContext) -> User? {
guard !firstName.isEmpty else { print("firstName can't be empty"); return nil }
guard !lastName.isEmpty else { print("lastName can't be empty"); return nil }
// Imagine we have some kind of debug user... Does not really make sense, but good for making a point.
guard firstName != "DEBUG" else { return User.debugUser }
let fetchRequest = NSFetchRequest(entityName: Users.entityName)
let predicate = NSPredicate(format: "firstName == \(firstName) AND lastName == \(lastName)")
fetchRequest.predicate = predicate
do {
let user = try context.executeFetchRequest(fetchRequest)
return user.first as? User
} catch let error as NSError {
print("Error fetching user: \(error)")
}
return nil
}
let returnValue = innerFunc(firstName, andLastName: lastName, fromContext: context)
print("return value: \(returnValue)")
return returnValue
}

Unwrapping multiple optionals in swift

I want to load a PDF that is in my application bundle into a CGPDFDocument.
Is there some way of calling a function that if any of the parameters that don't accept options have values that are nil, the function isn't called and nil is returned.
eg:
let pdfPath : String? = NSBundle.mainBundle().pathForResouce("nac_06", ofType:"pdf")
//I want to do this
let data : NSData? = NSData(contentsOfFile:pdfPath)
//I have to do this
let data : NSData? = pdfPath != nil ? NSData(contentsOfFile:pdfPath) : nil
let doc : CGPDFDocumentRef? = CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithCFData(data));
//pageView.pdf is optional, nicely this function accepts the document as an optional
pageView.pdfPage = CGPDFDocumentGetPage(doc, 1);
Because NSData.init?(contentsOfFile path:String), doesn't define path as optional, even though it is has an optional return value, I have to check before and if the parameter is nil, return nil. Is there some syntactic sugar for the data assignment (instead of the ?: operator)?
Either use multiple optional bindings separated by commas
func loadPDF() -> CGPDFDocumentRef?
{
if let pdfPath = NSBundle.mainBundle().pathForResouce("nac_06", ofType:"pdf"),
data = NSData(contentsOfFile:pdfPath),
doc = GPDFDocumentCreateWithProvider(CGDataProviderCreateWithCFData(data)) {
return doc
} else {
return nil
}
}
or use the guard statement
func loadPDF() -> CGPDFDocumentRef?
{
guard let pdfPath = NSBundle.mainBundle().pathForResouce("nac_06", ofType:"pdf") else { return nil }
guard let data = NSData(contentsOfFile:pdfPath) else { return nil }
return GPDFDocumentCreateWithProvider(CGDataProviderCreateWithCFData(data))
}
All explicit type annotations are syntactic sugar and not needed.
Edit:
In your particular case you need only to check if the file exists and even this – the file is missing – is very unlikely in iOS. Another benefit is to be able to return a non-optional PDFDocument.
func loadPDF() -> CGPDFDocumentRef
{
guard let pdfPath = NSBundle.mainBundle().pathForResource("nac_06", ofType:"pdf") else {
fatalError("file nac_06.pdf does not exist")
}
let data = NSData(contentsOfFile:pdfPath)
return CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithCFData(data!))!
}
I assume that you also don't want to continue with the execution of the function if pdfPath or data is nil. In this case, guard would be the best choice:
guard let pdfPath = NSBundle.mainBundle().pathForResouce("nac_06", ofType:"pdf") else {
// eventually also report some error
return
}
guard let data = NSData(contentsOfFile:pdfPath) else {
// eventually also report some error
return
}
// at this point you have a valid data object
You could also combine this into a single guard statement, to reduce the code duplication, you'll loose however in this case the possibility to know which of the two failed.
guard let pdfPath = NSBundle.mainBundle().pathForResource("nac_06", ofType:"pdf"),
data = NSData(contentsOfFile:pdfPath) else {
// eventually also report some error
return
}
There is two ways to achieve this.
Extend NSData class and create your own convenience init? method
Use the guard statement
I prefer the second method:
func getPDF(path : String?) -> CGPDFDocumentRef?
{
guard let filePath = path,
data = NSData(contentsOfFile: filePath),
pdf = GPDFDocumentCreateWithProvider(CGDataProviderCreateWithCFData(data)) else
{
return nil
}
return pdf
}
Call the method like:
let doc = getPDF(path : NSBundle.mainBundle().pathForResouce("nac_06", ofType:"pdf"))
You could do something fancy by defining a custom operator to deal with this situation. For example:
infix operator ^> {associativity left precedence 150}
func ^><T, U>(arg: T?, f: T->U?) -> U?{
if let arg = arg {
return f(arg)
} else {
return nil
}
}
The operator takes an optional left-side argument and a function that takes a non-optional and returns another optional as a right-side argument.
You could then write your code like this:
let pdfPath = NSBundle.mainBundle().pathForResource("nac_06", ofType:"pdf")
//the line below needs a NSData extension
let data = pdfPath ^> NSData.fileContents
let doc = data ^> CGDataProviderCreateWithCFData ^> CGPDFDocumentCreateWithProvider
//pageView.pdf is optional, nicely this function accepts the document as an optional
pageView.pdfPage = CGPDFDocumentGetPage(doc, 1)
Note that for this to work you need to add an extension to NSData, as you cannot map the init(contentsOfFile:) initializer to a generic function that can be passed to ^>.
extension NSData {
class func fileContents(path: String) -> NSData? {
return NSData(contentsOfFile: path)
}
}
The usage of the ^> operator reverts however the order you write the function names, if you prefer having the function names in the same order as the original code, you can add a reversed operator that does the same thing:
infix operator ^< {associativity right precedence 150}
func ^< <T, U>(f: T->U?, arg: T?) -> U?{
if let arg = arg {
return f(arg)
} else {
return nil
}
}
let pdfPath = NSBundle.mainBundle().pathForResource("nac_06", ofType:"pdf")
let data = NSData.fileContents ^< pdfPath
let doc = CGPDFDocumentCreateWithProvider ^< CGDataProviderCreateWithCFData ^< data
//pageView.pdf is optional, nicely this function accepts the document as an optional
pageView.pdfPage = CGPDFDocumentGetPage(doc, 1)

How to validate an e-mail address in swift?

Does anyone know how to validate an e-mail address in Swift? I found this code:
- (BOOL) validEmail:(NSString*) emailString {
if([emailString length]==0){
return NO;
}
NSString *regExPattern = #"[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSRegularExpression *regEx = [[NSRegularExpression alloc] initWithPattern:regExPattern options:NSRegularExpressionCaseInsensitive error:nil];
NSUInteger regExMatches = [regEx numberOfMatchesInString:emailString options:0 range:NSMakeRange(0, [emailString length])];
NSLog(#"%i", regExMatches);
if (regExMatches == 0) {
return NO;
} else {
return YES;
}
}
but I can't translate it to Swift.
I would use NSPredicate:
func isValidEmail(_ email: String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPred = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailPred.evaluate(with: email)
}
for versions of Swift earlier than 3.0:
func isValidEmail(email: String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPred = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailPred.evaluate(with: email)
}
for versions of Swift earlier than 1.2:
func isValidEmail(email: String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
if let emailPred = NSPredicate(format:"SELF MATCHES %#", emailRegEx) {
return emailPred.evaluateWithObject(email)
}
return false
}
As a String class extension
SWIFT 4
extension String {
func isValidEmail() -> Bool {
// here, `try!` will always succeed because the pattern is valid
let regex = try! NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .caseInsensitive)
return regex.firstMatch(in: self, options: [], range: NSRange(location: 0, length: count)) != nil
}
}
Usage
if "rdfsdsfsdfsd".isValidEmail() {
}
Editing, updated for Swift 3:
func validateEmail(enteredEmail:String) -> Bool {
let emailFormat = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPredicate = NSPredicate(format:"SELF MATCHES %#", emailFormat)
return emailPredicate.evaluate(with: enteredEmail)
}
Original answer for Swift 2:
func validateEmail(enteredEmail:String) -> Bool {
let emailFormat = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPredicate = NSPredicate(format:"SELF MATCHES %#", emailFormat)
return emailPredicate.evaluateWithObject(enteredEmail)
}
It's working fine.
If you are looking for a clean and simple solution to do this, you should take a look at https://github.com/nsagora/validation-components.
It contains an email validation predicate which is easy integrate in your code:
let email = "test#example.com"
let rule = EmailValidationPredicate()
let isValidEmail = rule.evaluate(with: email)
Behind the hood it uses the RFC 5322 reg ex (http://emailregex.com):
let regex = "(?:[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}" +
"~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\" +
"x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")#(?:(?:[\\p{L}0-9](?:[a-" +
"z0-9-]*[\\p{L}0-9])?\\.)+[\\p{L}0-9](?:[\\p{L}0-9-]*[\\p{L}0-9])?|\\[(?:(?:25[0-5" +
"]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-" +
"9][0-9]?|[\\p{L}0-9-]*[\\p{L}0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21" +
"-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"
(Preamble. Be aware that in some cases, you can now use this solution built-in to iOS: https://multithreaded.stitchfix.com/blog/2016/11/02/email-validation-swift/ )
The only solution:
1 - it avoids the horrific regex mistakes often seen in example code
2 - it does NOT allow ridiculous emails such as "x#x"
(If for some reason you need a solution that allows nonsense strings such as 'x#x', use another solution.)
3 - the code is extremely understandable
4 - it is KISS, reliable, and tested to destruction on commercial apps with enormous numbers of users
5 - the predicate is a global, as Apple says it must be
let __firstpart = "[A-Z0-9a-z]([A-Z0-9a-z._%+-]{0,30}[A-Z0-9a-z])?"
let __serverpart = "([A-Z0-9a-z]([A-Z0-9a-z-]{0,30}[A-Z0-9a-z])?\\.){1,5}"
let __emailRegex = __firstpart + "#" + __serverpart + "[A-Za-z]{2,8}"
let __emailPredicate = NSPredicate(format: "SELF MATCHES %#", __emailRegex)
extension String {
func isEmail() -> Bool {
return __emailPredicate.evaluate(with: self)
}
}
extension UITextField {
func isEmail() -> Bool {
return self.text?.isEmail() ?? false
}
}
It's that easy.
Explanation for anyone new to regex:
In this description, "OC" means ordinary character - a letter or a digit.
__firstpart ... has to start and end with an OC. For the characters in the middle you can have certain characters such as underscore, but the start and end have to be an OC. (However, it's ok to have only one OC and that's it, for example: j#blah.com)
__serverpart ... You have sections like "blah." which repeat. (Example, mail.city.fcu.edu.) The sections have to start and end with an OC, but in the middle you can also have a dash "-". It's OK to have a section which is just one OC. (Example, w.campus.edu) You can have up to five sections, you have to have one. Finally the TLD (such as .com) is strictly 2 to 8 in size . (Obviously, just change the "8" as preferred by your support department.)
IMPORTANT !
You MUST keep the predicate as a global, do not build it every time.
Note that this is the first thing Apple mentions about the whole issue in the docs.
Suggestions which do not cache the predicate are non-starters.
Non-english alphabets
Naturally, if you deal with non-english alphabets, adjust appropriately.
Simplest way in Swift 5
extension String {
var isValidEmail: Bool {
NSPredicate(format: "SELF MATCHES %#", "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,}").evaluate(with: self)
}
}
Example
"kenmueller0#gmail.com".isValidEmail
returns...
true
Here is a fuse of the two most up-voted answer with the correct regex: a String extension using predicate so you can call string.isEmail
extension String {
var isEmail: Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,20}"
let emailTest = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailTest.evaluateWithObject(self)
}
}
I would suggest using it as an extension of String:
extension String {
public var isEmail: Bool {
let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
let firstMatch = dataDetector?.firstMatch(in: self, options: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange(location: 0, length: length))
return (firstMatch?.range.location != NSNotFound && firstMatch?.url?.scheme == "mailto")
}
public var length: Int {
return self.characters.count
}
}
And to use it:
if "hodor#gameofthrones.com".isEmail { // true
print("Hold the Door")
}
This is the updated version for Swift 2.0 - 2.2
var isEmail: Bool {
do {
let regex = try NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .CaseInsensitive)
return regex.firstMatchInString(self, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count)) != nil
} catch {
return false
}
}
There are a lot of right answers here, but many of the "regex" are incomplete and it can happen that an email like: "name#domain" results a valid email, but it is not. Here the complete solution:
extension String {
var isEmailValid: Bool {
do {
let regex = try NSRegularExpression(pattern: "(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")#(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])", options: .CaseInsensitive)
return regex.firstMatchInString(self, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count)) != nil
} catch {
return false
}
}
}
Here is a method based on rangeOfString:
class func isValidEmail(testStr:String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let range = testStr.rangeOfString(emailRegEx, options:.RegularExpressionSearch)
return range != nil
}
Note: updated TLD length.
Here is the definitive RegEx for email as per RFC 5322, note that this is best not used because it only checks the basic syntax of email addresses and does not check is the top level domain exists.
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*
| "(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]
| \\[\x01-\x09\x0b\x0c\x0e-\x7f])*")
# (?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?
| \[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}
(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:
(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]
| \\[\x01-\x09\x0b\x0c\x0e-\x7f])+)
\])
See Regular-Expressions.info for more complete information on email RegExs.
Note that no escaping as required by a language such as Objective-C or Swift.
I prefer use an extension for that. Besides, this url http://emailregex.com can help you to test if regex is correct. In fact, the site offers differents implementations for some programming languages. I share my implementation for Swift 3.
extension String {
func validateEmail() -> Bool {
let emailRegex = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"
return NSPredicate(format: "SELF MATCHES %#", emailRegex).evaluate(with: self)
}
}
This a new version for "THE REASONABLE SOLUTION" by #Fattie, tested on Swift 4.1 in a new file called String+Email.swift:
import Foundation
extension String {
private static let __firstpart = "[A-Z0-9a-z]([A-Z0-9a-z._%+-]{0,30}[A-Z0-9a-z])?"
private static let __serverpart = "([A-Z0-9a-z]([A-Z0-9a-z-]{0,30}[A-Z0-9a-z])?\\.){1,5}"
private static let __emailRegex = __firstpart + "#" + __serverpart + "[A-Za-z]{2,6}"
public var isEmail: Bool {
let predicate = NSPredicate(format: "SELF MATCHES %#", type(of:self).__emailRegex)
return predicate.evaluate(with: self)
}
}
So its usage is simple:
let str = "mail#domain.com"
if str.isEmail {
print("\(str) is a valid e-mail address")
} else {
print("\(str) is not a valid e-mail address")
}
I simply don't like to add a func to the String objects, as being an e-mail address is inherent to them (or not). So a Bool property would fit better than a func, from my understanding.
For swift 2.1: this works correctly with email foo#bar
extension String {
func isValidEmail() -> Bool {
do {
let regex = try NSRegularExpression(pattern: "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}", options: .CaseInsensitive)
return regex.firstMatchInString(self, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count)) != nil
} catch {
return false
}
}
}
Use of Swift 4.2
extension String {
func isValidEmail() -> Bool {
let regex = try? NSRegularExpression(pattern: "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))#((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$", options: .caseInsensitive)
return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.count)) != nil
}
func isValidName() -> Bool{
let regex = try? NSRegularExpression(pattern: "^[\\p{L}\\.]{2,30}(?: [\\p{L}\\.]{2,30}){0,2}$", options: .caseInsensitive)
return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.count)) != nil
} }
And used
if (textField.text?.isValidEmail())!
{
// bla bla
}
else
{
}
Make a simple test for a # and . and send a confirmation email.
Consider this:
Half of the world uses non-ASCII characters.
Regexes are slow and complex. Btw check at least for char/letter/Unicode range, not az.
You can’t afford full validation because RFC rules and corresponding regex are too complex.
I’m using this basic check:
// similar to https://softwareengineering.stackexchange.com/a/78372/22077
import Foundation
/**
Checks that
- length is 254 or less (see https://stackoverflow.com/a/574698/412916)
- there is a # which is not the first character
- there is a . after the #
- there are at least 4 characters after the #
*/
func isValidEmail(email: String) -> Bool {
guard email.count <= 254 else {
return false
}
let pos = email.lastIndex(of: "#") ?? email.endIndex
return (pos != email.startIndex)
&& ((email.lastIndex(of: ".") ?? email.startIndex) > pos)
&& (email[pos...].count > 4)
}
print(isValidEmail(email: "アシッシュ#ビジネス.コム")) // true
Note that
It is considerably faster than regex and NSDataDetector.
It correctly reports the following as valid:
Håkan.Söderström#malmö.se"
punnycode#XN--0ZWM56D.XN--HGBK6AJ7F53BBA"
试#例子.测试.مثال.آزمایشی"
foo.bar+something#blah.com"
m#foo.co.uk
It incorrectly reports the following as invalid –because they are actually valid but likely the product of a user error:
a # b
a#b
Related:
How far should one take e-mail address validation?
online email checker: https://isemail.info/
#JeffersonBe's answer is close, but returns true if the string is "something containing someone#something.com a valid email" which is not what we want. The following is an extension on String that works well (and allows testing for valid phoneNumber and other data detectors to boot.
/// Helper for various data detector matches.
/// Returns `true` iff the `String` matches the data detector type for the complete string.
func matchesDataDetector(type: NSTextCheckingResult.CheckingType, scheme: String? = nil) -> Bool {
let dataDetector = try? NSDataDetector(types: type.rawValue)
guard let firstMatch = dataDetector?.firstMatch(in: self, options: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange(location: 0, length: length)) else {
return false
}
return firstMatch.range.location != NSNotFound
// make sure the entire string is an email, not just contains an email
&& firstMatch.range.location == 0
&& firstMatch.range.length == length
// make sure the link type matches if link scheme
&& (type != .link || scheme == nil || firstMatch.url?.scheme == scheme)
}
/// `true` iff the `String` is an email address in the proper form.
var isEmail: Bool {
return matchesDataDetector(type: .link, scheme: "mailto")
}
/// `true` iff the `String` is a phone number in the proper form.
var isPhoneNumber: Bool {
return matchesDataDetector(type: .phoneNumber)
}
/// number of characters in the `String` (required for above).
var length: Int {
return self.characters.count
}
Create simple extension:
extension NSRegularExpression {
convenience init(pattern: String) {
try! self.init(pattern: pattern, options: [])
}
}
extension String {
var isValidEmail: Bool {
return isMatching(expression: NSRegularExpression(pattern: "^[A-Z0-9a-z\\._%+-]+#([A-Za-z0-9-]+\\.)+[A-Za-z]{2,4}$"))
}
//MARK: - Private
private func isMatching(expression: NSRegularExpression) -> Bool {
return expression.numberOfMatches(in: self, range: NSRange(location: 0, length: characters.count)) > 0
}
}
Example:
"b#bb.pl".isValidEmail //true
"b#bb".isValidEmail //false
You can extend following extension to anything you need: isValidPhoneNumber, isValidPassword etc...
I made a library designed for input validations and one of the "modules" allows you to easily validate a bunch of stuff...
For example to validate an email:
let emailTrial = Trial.Email
let trial = emailTrial.trial()
if(trial(evidence: "test#test.com")) {
//email is valid
}
SwiftCop is the library... hope it help!
Updated answer #Arsonik answer to Swift 2.2, using less verbose code than other offered solutions:
extension String {
func isValidEmail() -> Bool {
let regex = try? NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .CaseInsensitive)
return regex?.firstMatchInString(self, options: [], range: NSMakeRange(0, self.characters.count)) != nil
}
}
My only addition to the list of responses would be that for Linux, NSRegularExpression does not exist, it's actually RegularExpression
func isEmail() -> Bool {
let patternNormal = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"
#if os(Linux)
let regex = try? RegularExpression(pattern: patternNormal, options: .caseInsensitive)
#else
let regex = try? NSRegularExpression(pattern: patternNormal, options: .caseInsensitive)
#endif
return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.characters.count)) != nil
This compiles successfully on both macOS & Ubuntu.
Here is an extension in Swift 3
extension String {
func isValidEmail() -> Bool {
let emailRegex = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
return NSPredicate(format: "SELF MATCHES %#", emailRegex).evaluate(with: self)
}
}
Just use it like this:
if yourEmailString.isValidEmail() {
//code for valid email address
} else {
//code for not valid email address
}
Best solution with best result for
Swift 4.x
extension String {
func validateAsEmail() -> Bool {
let emailRegEx = "(?:[a-zA-Z0-9!#$%\\&‘*+/=?\\^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%\\&'*+/=?\\^_`{|}" +
"~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\" +
"x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")#(?:(?:[a-z0-9](?:[a-" +
"z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5" +
"]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-" +
"9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21" +
"-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"
let emailTest = NSPredicate(format:"SELF MATCHES[c] %#", emailRegEx)
return emailTest.evaluate(with: self)
}
}
I improved #Azik answer. I allow more special characters which are allowed by guidelines, as well as return a few extra edge cases as invalid.
The group think going on here to only allow ._%+- in the local part is not correct per guidelines. See #Anton Gogolev answer on this question or see below:
The local-part of the email address may use any of these ASCII
characters:
uppercase and lowercase Latin letters A to Z and a to z;
digits 0 to 9;
special characters !#$%&'*+-/=?^_`{|}~;
dot ., provided that it is not the first or last character unless quoted, and provided also that it does not appear consecutively unless quoted (e.g.
John..Doe#example.com is not allowed but "John..Doe"#example.com is
allowed);
space and "(),:;<>#[\] characters are allowed with
restrictions (they are only allowed inside a quoted string, as
described in the paragraph below, and in addition, a backslash or
double-quote must be preceded by a backslash);
comments are allowed
with parentheses at either end of the local-part; e.g.
john.smith(comment)#example.com and (comment)john.smith#example.com
are both equivalent to john.smith#example.com;
The code I use will not allow restricted out of place special characters, but will allow many more options than the majority of answers here. I would prefer more relaxed validation to error on the side of caution.
if enteredText.contains("..") || enteredText.contains("##")
|| enteredText.hasPrefix(".") || enteredText.hasSuffix(".con"){
return false
}
let emailFormat = "[A-Z0-9a-z.!#$%&'*+-/=?^_`{|}~]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPredicate = NSPredicate(format:"SELF MATCHES %#", emailFormat)
return emailPredicate.evaluate(with: enteredText)
In Swift 4.2 and Xcode 10.1
//Email validation
func isValidEmail(email: String) -> Bool {
let emailRegex = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
var valid = NSPredicate(format: "SELF MATCHES %#", emailRegex).evaluate(with: email)
if valid {
valid = !email.contains("Invalid email id")
}
return valid
}
//Use like this....
let emailTrimmedString = emailTF.text?.trimmingCharacters(in: .whitespaces)
if isValidEmail(email: emailTrimmedString!) == false {
SharedClass.sharedInstance.alert(view: self, title: "", message: "Please enter valid email")
}
If you want to use SharedClass.
//This is SharedClass
import UIKit
class SharedClass: NSObject {
static let sharedInstance = SharedClass()
//Email validation
func isValidEmail(email: String) -> Bool {
let emailRegex = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
var valid = NSPredicate(format: "SELF MATCHES %#", emailRegex).evaluate(with: email)
if valid {
valid = !email.contains("Invalid email id")
}
return valid
}
private override init() {
}
}
And call function like this....
if SharedClass.sharedInstance. isValidEmail(email: emailTrimmedString!) == false {
SharedClass.sharedInstance.alert(view: self, title: "", message: "Please enter correct email")
//Your code here
} else {
//Code here
}
Here's an up to date playground compatible version that uses the standard library so you don't have to maintain a regex:
import Foundation
func isValid(email: String) -> Bool {
do {
let detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
let range = NSRange(location: 0, length: email.count)
let matches = detector.matches(in: email, options: .anchored, range: range)
guard matches.count == 1 else { return false }
return matches[0].url?.scheme == "mailto"
} catch {
return false
}
}
extension String {
var isValidEmail: Bool {
isValid(email: self)
}
}
let email = "test#mail.com"
isValid(email: email) // prints 'true'
email.isValidEmail // prints 'true'
Majority of the above regex examples fail to catch error when there are even basic problems with emails. For example
h..1#nyu.edu - consecutive dots
ab1234#.nyu.edu - dot after #
a.bcdnle12.#email.com - dot before #
.abc#email.com - starts with a dot
Here is a string extension I have used that uses regex with tighter rules.
extension String {
func isValidEmail() -> Bool {
let emailRegEx = "^(?!\\.)([A-Z0-9a-z_%+-]?[\\.]?[A-Z0-9a-z_%+-])+#[A-Za-z0-9-]{1,20}(\\.[A-Za-z0-9]{1,15}){0,10}\\.[A-Za-z]{2,20}$"
let emailPred = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailPred.evaluate(with: self)
}
}
Here is how we can write test case for it.
XCTAssertFalse("ab1234#.nyu.edu".isValidEmail())
XCTAssertTrue("valid_email#email.com".isValidEmail())
Since there are so many weird top level domain name now, I stop checking the length of the top domain...
Here is what I use:
extension String {
func isEmail() -> Bool {
let emailRegEx = "^[a-zA-Z0-9_.+-]+#[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$"
return NSPredicate(format:"SELF MATCHES %#", emailRegEx).evaluateWithObject(self)
}
}
Seems to work too...
let regex = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
func validate(email: String) -> Bool {
let matches = email.rangeOfString(regex, options: .RegularExpressionSearch)
if let _ = matches {
return true
}
return false
}
And for Swift 3:
extension String {
func isValidEmail() -> Bool {
let regex = try? NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .caseInsensitive)
return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.characters.count)) != nil
}
}

Resources