有人知道如何在Swift中验证电子邮件地址吗?我找到了这个代码:

- (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;
    }
}

但我无法翻译成斯威夫特。


当前回答

这里有很多正确答案,但许多“正则表达式”是不完整的,可能会发生像“name@domain”这样的电子邮件结果是有效的电子邮件,但它不是。这里是完整的解决方案:

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
        }
    }
}

其他回答

我会使用npredicate:

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)
}

对于Swift 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)
}

对于Swift 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
}

下面是一个基于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
}

备注:更新TLD长度。

下面是符合RFC 5322的电子邮件的最终RegEx,请注意,最好不要使用它,因为它只检查电子邮件地址的基本语法,而不检查顶级域是否存在。

(?:[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])+)
     \])

有关电子邮件regex的更完整信息,请参阅Regular-Expressions.info。

注意,在Objective-C或Swift等语言中没有转义。

完美的正则表达式,如谷歌电子邮件

"^[A-Z0-9a-z][a-zA-Z0-9_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"

我更喜欢用扩展名。此外,这个url http://emailregex.com可以帮助您测试regex是否正确。事实上,该站点为某些编程语言提供了不同的实现。我分享了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)
    }
}

Swift 5 -可伸缩的验证层

使用此层,您将轻松地在任何文本字段上获得惊人的验证。

只需遵循以下流程即可。

1. 添加这些枚举:

import Foundation

enum ValidatorType
{
    case email
    case name
    // add more cases ...
}

enum ValidationError: Error, LocalizedError
{
    case invalidUserName
    case invalidEmail
    // add more cases ...

    var localizedDescription: String
    {
        switch self
        {
        case .invalidEmail:
            return "Please kindly write a valid email"    
        case .invalidUserName:
            return "Please kindly write a valid user name"
        }
    }
}

2. 将此功能添加到String:

extension String
{
    // MARK:- Properties

    var isValidEmail: 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: self)
    }

    // MARK:- Methods

    func validatedText(_ validationType: ValidatorType) throws
    {
        switch validationType
        {
            case .name:
                try validateUsername()
            case .email:
                try validateEmail()
        }
    }

    // MARK:- Private Methods

    private func validateUsername() throws
    {
        if isEmpty
        {
            throw ValidationError.invalidUserName
        }
    }

    private func validateEmail() throws
    {
        if !isValidEmail 
        {
            throw ValidationError.invalidEmail
        }

        // add more validations if you want like empty email
    }
}

3.添加以下功能到UITextField:

import UIKit

extension UITextField
{
    func validatedText(_ validationType: ValidatorType) throws
    {
        do
        {
            try text?.validatedText(validationType)
        }
        catch let validationError
        {
            shake()
            throw validationError
        }
    }

    // MARK:- Private Methods

    private func shake()
    {
        let animation = CABasicAnimation(keyPath: "position")
        animation.duration = 0.1
        animation.repeatCount = 5
        animation.fromValue = NSValue(cgPoint: CGPoint(x: center.x + 6, y: center.y))
        animation.toValue = NSValue(cgPoint: CGPoint(x: center.x - 6, y: center.y))
        layer.add(animation, forKey: "position")
    }
}

使用

import UIKit

class LoginVC: UIViewController
{
    // MARK: Outlets

    @IBOutlet weak var textFieldEmail: UITextField!

    // MARK: View Controller Life Cycle

    override func viewDidLoad()
    {
        super.viewDidLoad()
    }

    // MARK: Methods

    private func checkEmail() -> Bool
    {
        do
        {
            try textFieldEmail.validatedText(.email)
        }
        catch let error
        {
            let validationError = error as! ValidationError
            // show alert to user with: validationError.localizedDescription
            return false
        }

        return true
    }

    // MARK: Actions

    @IBAction func loginTapped(_ sender: UIButton)
    {
        if checkEmail()
        {
            let email = textFieldEmail.text!
            // move safely ...
        }
    }
}