How to remove diacritics (or accents) from a String
(like say change "één" to "een") in Swift? Do I have to go back to NSString
or can it be done within Swift?
Asked
Active
Viewed 3.1k times
96

Leo Dabus
- 229,809
- 59
- 489
- 571

Johan Kool
- 15,637
- 8
- 64
- 81
5 Answers
196
You can operate directly on a Swift String
(if "Foundation" is imported):
let foo = "één"
let bar = foo.stringByFoldingWithOptions(.DiacriticInsensitiveSearch, locale: NSLocale.currentLocale())
print(bar) // een
Swift 3:
let foo = "één"
let bar = foo.folding(options: .diacriticInsensitive, locale: .current)
print(bar) // een

Martin R
- 529,903
- 94
- 1,240
- 1,382
-
Excellent answer as always. Note that stringByFoldingWithOptions is a method from NSString. This takes advantage of the seamless bridging between NSString and String in Swift 2. Things are different in Swift 3. – Duncan C Oct 28 '16 at 11:14
-
3@codddeer123: Looks like similar case as in https://stackoverflow.com/a/16837527/1187415: U-0141 LATIN CAPITAL LETTER L WITH STROKE does not have a decomposition into a base character and a combining mark. Or (as I understand it) the Unicode standard does not define a relationship between `Ł` and `L`. – Martin R Apr 09 '18 at 19:13
-
@MartinR, thanks for quick response. So in case of Ł i should remove it manually? – mikro098 Apr 09 '18 at 19:17
-
@codddeer123: I do not know a better solution. – Martin R Apr 09 '18 at 19:25
-
This is fantastic! If I set it with "locale: .current" and then the app is used in a country where the current locale supports some type of accented character, will that make a difference? Is there a difference in making this call with "locale: nil" vs .current? – RanLearns May 24 '18 at 17:30
-
2@RanLearns: I *assume* that `locale: nil` will apply the general Unicode rules, and `locale: .current` those of the current languages. But I have not tested it. – Martin R May 24 '18 at 19:52
-
@MartinR `Locale: nil` uses the system locale. – xian Apr 28 '19 at 11:40
-
I tried, any to keep space in result String? – Kien Vu Jul 26 '21 at 04:07
23
Update to @MartinR's answer… a Swift 3 extension to provide a string for sorting / searching, that might be useful for someone…
extension String {
var forSorting: String {
let simple = folding(options: [.diacriticInsensitive, .widthInsensitive, .caseInsensitive], locale: nil)
let nonAlphaNumeric = CharacterSet.alphanumerics.inverted
return simple.components(separatedBy: nonAlphaNumeric).joined(separator: "")
}
}
e.g.
print("Mÿ nâMe ís jÄço´B".forSorting) // "mynameisjacob"

Ashley Mills
- 50,474
- 16
- 129
- 160
-
1You should now that sorting is very locale dependent. For example, in my language "ch" is one letter between "h" "i". For sorting thay is diacritics insensitive just use the correct string search options. – Sulthan Oct 27 '16 at 10:36
-
7
9
This is my solutión
Swift 5
extension String {
func unaccent() -> String {
return self.folding(options: .diacriticInsensitive, locale: .current)
}
}

Danielvgftv
- 547
- 7
- 6
7
This can also be done applying a StringTransform
:
let foo = "één"
let bar = foo.applyingTransform(.stripDiacritics, reverse: false)!
print(bar) // een
Or implementing a custom property to StringProtocol
extension StringProtocol {
var stripingDiacritics: String {
applyingTransform(.stripDiacritics, reverse: false)!
}
}
let bar = foo.stripingDiacritics
print(bar) // een

Leo Dabus
- 229,809
- 59
- 489
- 571
0
Answer update for Swift 5.0.1
func toNoSmartQuotes() -> String {
let userInput: String = self
return userInput.folding(options: .diacriticInsensitive, locale: .current)
}
and use it someTextField.text.toNoSmartQuotes()

amagain
- 2,042
- 2
- 20
- 36
-
4Just be aware that the change is larger than what your method name implies. – Johan Kool Nov 14 '19 at 09:22