有人知道如何在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;
    }
}

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


当前回答

这是@Fattie的“THE REASONABLE SOLUTION”的新版本,在Swift 4.1的一个名为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)
    }
}

所以它的用法很简单:

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

我只是不喜欢向String对象添加func,因为作为电子邮件地址是它们固有的(或不是)。根据我的理解,Bool属性比func更适合。

其他回答

这里有很多正确答案,但许多“正则表达式”是不完整的,可能会发生像“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
}

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

这是一个最新的游乐场兼容版本,使用标准库,所以你不需要维护一个正则表达式:

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'

对于那些还在寻找答案的人,请看看下面的框架;

ATGvalidator

它是一个基于规则的验证框架,可以处理大部分开箱即用的验证。最重要的是,它有表单验证器,支持同时验证多个文本字段。

要验证电子邮件字符串,请使用以下方法;

"abcd.hhs@some.com".satisfyAll(rules: [StringRegexRule.email]).status

如果你想验证从文本字段的电子邮件,尝试下面的代码;

textfield.validationRules = [StringRegexRule.email]
textfield.validationHandler = { result in
    // This block will be executed with relevant result whenever validation is done.
    print(result.status, result.errors)
}
// Below line is to manually trigger validation.
textfield.validateTextField()

如果您想在文本框中输入或当焦点更改到另一个字段时验证它,请添加以下行之一;

textfield.validateOnInputChange(true)
// or
textfield.validateOnFocusLoss(true)

请在链接处查看自述文件以获取更多用例。