(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.