Bad practice: not using PersonNameComponentsFormatter
You’re more of a video kind of person? I’ve got you covered! Here’s a video with the same content than this article 🍿
Can you guess what’s the problem with this code?
If you live in a western country, there’s a good chance this code seems perfectly reasonable: we format the fullName of the User by using String interpolation.
However, while most western countries indeed format a fullName by writing the givenName first and the familyName second, not all countries follow this convention!
For instance, Koreans write the familyName first and the givenName second.
And as you can imagine, if your app doesn’t follow this local convention, it will feel weird and out-of-place with a part of your audience!
Fortunately, iOS has a built-in way to solve this problem!
For this, we’re going to use a class called PersonNameComponentsFormatter.
PersonNameComponentsFormatter works in a similar way to other formatters like NumberFormatter or DateFormatter: you give it raw data and it formats it according to the user’s Locale.
So I’m going to update the implementation of the property fullName to use a PersonNameComponentsFormatter rather than String interpolation.
As you can see, the new implementation yields the same result than the previous one:
That’s normal because my Locale is currently set to French, and this is indeed how a fullName would be displayed in France.
But if I update the Locale to be that of Korea, you can see that the behavior of the formatter is now matching that of the new Locale: the fullName is now formatted with the familyName first, and the givenName second.
That’s all for this article, I hope you’ve enjoyed discovering how PersonNameComponentsFormatter works!
Here’s the code if you want to experiment with it:
import Foundation
struct User {
let givenName: String
let familyName: String
}
let personNameFormatter = PersonNameComponentsFormatter()
extension User {
var fullName: String {
var components = PersonNameComponents()
components.givenName = givenName
components.familyName = familyName
return personNameFormatter.string(from: components)
}
}
let user = User(
givenName: "Vincent",
familyName: "Pradeilles"
)
user.fullName // Vincent Pradeilles
let koreanLocale = Locale(identifier: "ko_KR")
personNameFormatter.locale = koreanLocale
user.fullName // Pradeilles Vincent