In Swift, how can I check if a String
is alphanumeric, ie, if it contains only one or more alphanumeric characters [a-zA-Z0-9]
, excluding letters with diacritics, eg, é.

- 121,420
- 116
- 450
- 651
-
In Objective-C: http://stackoverflow.com/questions/1671605/how-to-check-if-a-string-only-contains-alphanumeric-characters-in-objective-c – ma11hew28 Mar 14 '16 at 16:23
8 Answers
extension String {
var isAlphanumeric: Bool {
return !isEmpty && range(of: "[^a-zA-Z0-9]", options: .regularExpression) == nil
}
}
"".isAlphanumeric // false
"abc".isAlphanumeric // true
"123".isAlphanumeric // true
"ABC123".isAlphanumeric // true
"iOS 9".isAlphanumeric // false

- 121,420
- 116
- 450
- 651
-
-
4
-
@TimVermeulen That'd work too. I guess I went with a method because it does quite a bit more checking than say `Set.isEmpty`. Also, [in Python, `str.isalnum()` is a method](https://docs.python.org/library/stdtypes.html#str.isalnum). – ma11hew28 Mar 14 '16 at 21:49
-
@KennethBruno I tried that, but in iOS 9.2, `[:alnum:]` includes letters with diacritics, e.g., é, which is not what I want. I just reported this issue to Apple. – ma11hew28 Mar 14 '16 at 23:29
-
Yes, it does. If you want to exclude letters outside the ASCII character set use: `^([:ascii:]|[:alnum])+$`. The benefit of this over the one in the answer is that your intent is clearer, it's plain you want only ASCII and alphanumeric characters. – Mar 15 '16 at 00:10
-
@MattDiPasquale I don't really agree with your reasoning, whether a string is alphanumeric or not is a property, no matter how it was computed. – Tim Vermeulen Mar 15 '16 at 12:44
-
1@TimVermeulen well, another reason I initially made it a method is that Swift has methods like `UnicodeDecodingResult.isEmptyInput()` & `UnicodeScalar.isASCII()`. But, I just noticed that Swift also has properties like `String.isEmpty`, `StaticString.isASCII`, and `Float.isNaN`. So, I changed it to a property. I also made a couple Swift bug reports: https://bugs.swift.org/browse/SR-950 & https://bugs.swift.org/browse/SR-951. – ma11hew28 Mar 15 '16 at 18:47
-
Yeah, `UIKit` still isn't very consistent regarding properties and functions (among other things). Thanks for reporting, I voted for them. – Tim Vermeulen Mar 15 '16 at 18:52
-
@TimVermeulen sure. Thanks! :-) And, thank you for your feedback here. – ma11hew28 Mar 15 '16 at 19:16
-
@KennethBruno thank you, but `[a-zA-Z0-9]` is shorter & (to me) more explicit. I don't always remember (and so have to look up) which characters the `[:ascii:]` & `[:alnum:]` POSIX character classes include—Not to mention, acronyms (like ASCII) & abbreviations (like alnum) tend to sacrifice clarity. Also, I thought `(a|b)` meant `a` or `b`, so it's unclear to me that `([:ascii:]|[:alnum])` means `[:ascii:]` *and* `[:alnum]`. – ma11hew28 Mar 15 '16 at 19:32
-
The nature of the code is that we want to include anything that is `not (ascii or alphanumeric)`, translating that with [De Morgan's laws](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) we get including anything that is `(not ascii) and (not alphanumeric)`. So you can express it with either `and` or `or`, it just takes knowing the algorithms deeply enough. Of course, use whatever works best for you! – Mar 15 '16 at 21:05
-
1
-
-
-
@Soumen I implemented this property to work like [Python's isalnum](https://docs.python.org/3/library/stdtypes.html#str.isalnum) method, which returns true if the string isn't empty and all of its characters are alphanumeric. – ma11hew28 Jun 18 '18 at 14:10
A modern Swift 3 and 4 solution
extension String {
func isAlphanumeric() -> Bool {
return self.rangeOfCharacter(from: CharacterSet.alphanumerics.inverted) == nil && self != ""
}
func isAlphanumeric(ignoreDiacritics: Bool = false) -> Bool {
if ignoreDiacritics {
return self.range(of: "[^a-zA-Z0-9]", options: .regularExpression) == nil && self != ""
}
else {
return self.isAlphanumeric()
}
}
}
Usage:
"".isAlphanumeric() == false
"Hello".isAlphanumeric() == true
"Hello 2".isAlphanumeric() == false
"Hello3".isAlphanumeric() == true
"Français".isAlphanumeric() == true
"Français".isAlphanumeric(ignoreDiacritics: true) == false
This works with languages other than English, allowing diacritic characters like è and á, etc. If you'd like to ignore these, use the flag "ignoreDiacritics: true
".

- 1,293
- 14
- 15
-
1This should be the accepted answer. It's cleaner and I suspect it will perform better than any RegEx expression. – R OMS Oct 21 '17 at 14:18
-
But, this solution allows letters with diacritics, eg, é, which is not what I want. – ma11hew28 Oct 21 '17 at 14:32
-
@ma11hew28 you should consider allowing for diacritics. Input can unexpectedly have them if user input is anywhere in your code. They are alpha numeric. – gavanon Oct 21 '17 at 14:37
-
Thank you, @gavanon, I will consider it. But, I am validating usernames for a platform, and I want the users to be able to use the their usernames for their accounts on other platforms, such as Facebook & Instagram, neither of which allow usernames to contain letters with diacritics. – ma11hew28 Oct 21 '17 at 14:49
-
@ma11hew28 That's to avoid people creating fake accounts like "Mícrosoft" (See what I did there?). I see you updated your question stressing the ignoring of diacritics, so I've included the ability to ignore them in my edited answer. :) – gavanon Oct 21 '17 at 17:08
-
Nice. Thank you. :-) I think you can delete the first function from your answer and just use its body in the second function. No, sorry, I don't see what you did there. ¯\\_(ツ)_/¯ – ma11hew28 Oct 22 '17 at 04:14
-
I’ll leave both just for those who want the extra feature. As for Mícrosoft, what I did was use a special í with a diacritic. You didn’t even notice - hence why they’re not allowed in Twitter user names. ;) – gavanon Oct 22 '17 at 14:52
-
I felt the accepted answer using regex was concrete but a rather heavy solution. You could check it this way also in Swift 3.0:
if yourString.rangeOfCharacter(from: CharacterSet.alphanumerics.inverted) != nil {
return "Username can only contain numbers or digits"
}

- 6,049
- 5
- 46
- 73
-
2
-
3Thank you, but this solution allows letters with diacritics, eg, é, which is not what I want. – ma11hew28 Oct 21 '17 at 14:39
-
Excellent answer. I think CharacterSet was introduced exactly to get rid of regulars usage – rommex Sep 19 '19 at 11:49
extension String {
/// Allows only `a-zA-Z0-9`
public var isAlphanumeric: Bool {
guard !isEmpty else {
return false
}
let allowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
let characterSet = CharacterSet(charactersIn: allowed)
guard rangeOfCharacter(from: characterSet.inverted) == nil else {
return false
}
return true
}
}
XCTAssertFalse("".isAlphanumeric)
XCTAssertFalse("climate change".isAlphanumeric)
XCTAssertFalse("Poüet".isAlphanumeric)
XCTAssertTrue("Hawking2018".isAlphanumeric)

- 50,398
- 25
- 166
- 151
-
Checked now and find it's working. I was checking in the playground may be made some mistake then. Thanks. – Soumen May 23 '18 at 12:12
The problem with the CharacterSet.alphanumerics
CharacterSet is that it is more permissive than [a-zA-Z0-9]
. It contains letters with diacritics, Eastern Arabic numerals, etc.
assert(["e", "E", "3"].allSatisfy({ CharacterSet.alphanumerics.contains($0) }))
assert(["ê", "É", "٣"].allSatisfy({ CharacterSet.alphanumerics.contains($0) }))
You can build your own CharacterSet
using only the specific 62 "alphanumeric" characters:
extension CharacterSet {
static var alphanumeric62: CharacterSet {
return lowercase26.union(uppercase26).union(digits10)
}
static var lowercase26: CharacterSet { CharacterSet(charactersIn: "a"..."z") }
static var uppercase26: CharacterSet { CharacterSet(charactersIn: "A"..."Z") }
static var digits10: CharacterSet { CharacterSet(charactersIn: "0"..."9") }
}
assert(["e", "E", "3"].allSatisfy({ CharacterSet.alphanumeric62.contains($0) }))
assert(["ê", "É", "٣"].allSatisfy({ CharacterSet.alphanumeric62.contains($0) == false }))
Then test your string against the inverse of that CharacterSet:
guard "string".rangeOfCharacter(from: CharacterSet.alphanumeric62.inverted) == nil else {
fatalError()
}

- 33,281
- 23
- 160
- 191
Here's a succinct approach:
extension String {
var isAlphanumeric: Bool {
allSatisfy { $0.isLetter || $0.isNumber }
}
}

- 5,018
- 4
- 34
- 46
-
1Problem with this approach is it will allow diacritical variants, such as `é`. A workaround is to add `$0.isASCII` to the check. – Ranoiaetep May 12 '22 at 05:33
This regex used to check that string contains atleast 1 alphabet + atleast 1 digit alongwith 8 characters.
"^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$"

- 4,851
- 5
- 38
- 73

- 39
- 1
extension String {
var isAlphaNumeric: Bool {
let hasLetters = rangeOfCharacter(from: .letters, options: .numeric, range: nil) != nil
let hasNumbers = rangeOfCharacter(from: .decimalDigits, options: .literal, range: nil) != nil
let comps = components(separatedBy: .alphanumerics)
return comps.joined(separator: "").count == 0 && hasLetters && hasNumbers
}
}

- 295
- 1
- 3
- 16