我使用以下扩展名来确保字符串至少有 1 个数字、1 个字母和 5-15 个字符的长度,我觉得它可以更有效率。有什么建议吗?
func checkPassword(password: String) -> Bool{
if password.characters.count > 15 || password.characters.count < 5 {
return false
}
let capitalLetterRegEx = ".*[A-Za-z]+.*"
let texttest = NSPredicate(format:"SELF MATCHES %@", capitalLetterRegEx)
let capitalresult = texttest.evaluate(with: password)
let numberRegEx = ".*[0-9]+.*"
let texttest1 = NSPredicate(format:"SELF MATCHES %@", numberRegEx)
let numberresult = texttest1.evaluate(with: password)
let specialRegEx = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ0123456789"
let texttest2 = NSPredicate(format:"SELF MATCHES %@", specialRegEx)
let specialresult = !texttest2.evaluate(with: password)
if !capitalresult || !numberresult || !specialresult {
return false
}
return true
}
使用 Regex
正则表达式是一种方法,但如果使用它,我们可能会将您的规范合并到单个正则表达式搜索中,利用以下问答中的积极前瞻断言技术:
- 用于验证密码强度的正则表达式
在这里,使用正则表达式:
^(?=.*[A-Za-z])(?=.*[0-9])(?!.*[^A-Za-z0-9]).{5,15}$
// where:
// (?=.*[A-Za-z]) Ensures string has at least one letter.
// (?=.*[0-9]) Ensures string has at least one digit.
// (?!.*[^A-Za-z0-9]) Ensures string has no invalid (non-letter/-digit) chars.
// .{5,15} Ensures length of string is in span 5...15.
我还包含一个负面的前瞻断言 (?!...
),以使任何无效字符的密码无效。
我们可以按如下方式实现正则表达式搜索:
extension String {
func isValidPassword() -> Bool {
let regexInclude = try! NSRegularExpression(pattern: "^(?=.*[A-Za-z])(?=.*[0-9])(?!.*[^A-Za-z0-9]).{5,15}$")
return regexInclude.firstMatch(in: self, options: [], range: NSRange(location: 0, length: characters.count)) != nil
}
}
let pw1 = "hs1bés2" // invalid character
let pw2 = "12345678" // no letters
let pw3 = "shrt" // short
let pw4 = "A12345" // ok
print(pw1.isValidPassword()) // false
print(pw2.isValidPassword()) // false
print(pw3.isValidPassword()) // false
print(pw4.isValidPassword()) // true
使用Set
/CharacterSet
Swift 原生方法是使用显式指定的Character
集:
extension String {
private static var numbersSet = Set("1234567890".characters)
private static var alphabetSet = Set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ".characters)
func isValidPassword() -> Bool {
return 5...15 ~= characters.count &&
characters.contains(where: String.numbersSet.contains) &&
characters.contains(where: String.alphabetSet.contains)
}
}
或者,类似地,使用Foundation
方法rangeOfCharacter(from:)
超过CharacterSet
的:
extension String {
private static var numbersSet = CharacterSet(charactersIn: "1234567890")
private static var alphabetSet = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ")
func isValidPassword() -> Bool {
return 5...15 ~= characters.count &&
rangeOfCharacter(from: String.numbersSet) != nil &&
rangeOfCharacter(from: String.alphabetSet) != nil
}
}
如果您还想拒绝包含不在指定集中的任何字符的密码,则可以在集合的(倒置)并集上添加搜索操作(可能您还允许在此并集中包含一些特殊字符)。 例如,对于CharacterSet
示例:
extension String {
private static var numbersSet = CharacterSet(charactersIn: "1234567890")
private static var alphabetSet = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ")
func isValidPassword() -> Bool {
return 5...15 ~= characters.count &&
rangeOfCharacter(from: String.numbersSet.union(String.alphabetSet).inverted) == nil &&
rangeOfCharacter(from: String.numbersSet) != nil &&
rangeOfCharacter(from: String.alphabetSet) != nil
}
}
let pw1 = "hs1bés2" // invalid character
let pw2 = "12345678" // no letter
let pw3 = "shrt" // too short
let pw4 = "A12345" // OK
print(pw1.isValidPassword()) // false
print(pw2.isValidPassword()) // false
print(pw3.isValidPassword()) // false
print(pw4.isValidPassword()) // true
使用模式匹配
只是为了讨论它,另一种方法是使用本机 Swift 模式匹配:
extension String {
private static var numberPattern = Character("0")..."9"
private static var alphabetPattern = Character("a")..."z"
func isValidPassword() -> Bool {
return 5...15 ~= characters.count &&
characters.contains { String.numberPattern ~= $0 } &&
lowercased().characters.contains { String.alphabetPattern ~= $0 }
}
}
let pw1 = "hs1bs2"
let pw2 = "12345678"
let pw3 = "shrt"
let pw4 = "A12345"
print(pw1.isValidPassword()) // true
print(pw2.isValidPassword()) // false
print(pw3.isValidPassword()) // false
print(pw4.isValidPassword()) // true
请注意,这种方法将允许带有变音符号(和类似符号)的字母作为最小 1 个字母规范通过,例如:
let diacritic: Character = "é"
print(Character("a")..."z" ~= diacritic) // true
let pw5 = "12345é6"
print(pw5.isValidPassword()) // true
由于这些包含Character
范围"a"..."z"
;例如,请参阅以下线程中的出色答案:
- Swift 中的字符串和字符比较不区分区域设置是什么意思?
感谢您的回复。我用它们来创建这个:
extension String {
private static var numbersSet = Set("1234567890".characters)
private static var alphabetSet = Set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ".characters)
func isValidPassword() -> Bool {
let characterset = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLKMNOPQRSTUVWXYZ0123456789")
return 5...15 ~= characters.count &&
characters.contains(where: String.numbersSet.contains) &&
characters.contains(where: String.alphabetSet.contains) &&
self.rangeOfCharacter(from: characterset.inverted) != nil
}
}