Leonardo Maia Pugliese
Holy Swift

Holy Swift

Using Swift to Parse Person Name with iOS 15 APIs

Using Swift to Parse Person Name with iOS 15 APIs

What is your name?

Leonardo Maia Pugliese's photo
Leonardo Maia Pugliese
·Dec 9, 2021·

6 min read

Subscribe to my newsletter and never miss my upcoming articles

Hallo katten en poesjes, Leo hier.

Today we will explore the PersonNameComponents API from foundation. From time to time we are asked to parse a person name into our apps. There are plenty reasons for that: you need to show just the suffix of the name, you only want to put in the header of a screen the surname of the user, you may need to send to the backend in different fields the different parts of the name etc.

Good for us that Apple made an API ready to do that for us. Let's explore this API and see tips and tricks about the PersonNameComponents.

Let's code! But first...

The Painting

This painting is a 1850 portrait of Dom Pedro II from António de Souza Lobo. He was Brazilian's an artist who was born in 1840. The maker's first piece to be offered at auction was "A portrait of King Pedro IV of Portugal" at Veritas Art Auctioneers in 2021 The artist died in 1909.

I chose this painting because as we are talking about names, Dom Pedro ll had a giant name. The full name was: Pedro de Alcântara João Carlos Leopoldo Salvador Bibiano Francisco Xavier de Paula Leocádio Miguel Gabriel Rafael Gonzaga de Bragança e Bourbon. Imagine parse this into your apps?

The Problem

The user input his/her name into an UITextField and now you have to parse/split that name into parts so you can show in other screen just the surname or the given name.

Let's start in the beginning. How can we initialise the PersonNameComponents.

PersonNameComponents Initialisers

We have three ways to do so. The first one is letting Swift parse everything for us:

let name = "John Lennon"
var nameComponents = try PersonNameComponents(name)
print(nameComponents)

Pay attention that if you use this initialiser, it throws errors. So you will have to handle them if something wrong occurs in the automatic parsing.

Resulting in:

Screenshot 2021-12-08 at 08.20.41.png

This seems right to me, isn't it?

But If you already have the specific part of the name and know where it will fit in the PersonNameComponents, we have another option for you. I think this second initialiser can be suitable for most form input cases, where you have a UITextField for given name, another text field for the middle name and another one for the surname. You can use this initialiser:

let name = "John Lennon"
var nameComponents = PersonNameComponents(namePrefix: nil, givenName: name, middleName: nil, familyName: nil, nameSuffix: nil, nickname: nil)
print(nameComponents)

Now the call not throws anymore, and as we put the name exactly as the givenName, the result will be:

Screenshot 2021-12-08 at 08.26.09.png

The third initialiser useful initialiser is when you have complex rules to parse names. This way you have to create your own set of parsing rules. To do that we have to make it in two steps: first create the ParseStrategy that is a handy iOS 15 Swift protocol to parse anything into other things and then pass it to the PersonNameComponents to see magic happens.

The new iOS 15 ParseStrategy Protocol is very handy for parse a representation of a given data type, let's take a look at it first:

/// A type that can parse a representation of a given data type.
@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
public protocol ParseStrategy : Decodable, Encodable, Hashable {

    /// The type of the representation describing the data.
    associatedtype ParseInput

    /// The type of the data type.
    associatedtype ParseOutput

    /// Creates an instance of the `ParseOutput` type from `value`.
    func parse(_ value: Self.ParseInput) throws -> Self.ParseOutput
}

Now let's implement that for our use case. For our example imagine that encrypted names will be inserted, for the sake of simplicity I won't implement a full cryptography system but think that the decryptName function could be a LOT more complex:

struct NameParser: ParseStrategy {

    var defaultPersonName = PersonNameComponents(givenName: "John", familyName: "Doe")

    func parse(_ value: String) throws -> PersonNameComponents {

        guard let intValue = Int(value) else { return defaultPersonName }

        return try decryptName(intValue)
    }

    private func decryptName(_ value: Int) throws -> PersonNameComponents {

        switch value {
        case 1:
            return try PersonNameComponents("Lola Pa Loza")
        case 2:
            return try PersonNameComponents("Moon Lighter Fuz")
        case 3...7:
            return try PersonNameComponents("Hing Chong Lau")
        default:
            return defaultPersonName
        }
    }
}

Now you have to use the NameParser struct that conforms to ParseStrategy to decode names, like this:

let name = "1"
var nameComponents = try PersonNameComponents(name, strategy: NameParser())
print(nameComponents)

Resulting:

Screenshot 2021-12-09 at 07.53.53.png

One curious thing you can do is using the name parse function to map things. As they function requirements are the same, we can map them directly:

print(try ["1","2","3","8"].map(nameParser.parse(_:)))

With the expected result:

Screenshot 2021-12-09 at 07.55.57.png

Exploring the PersonNameComponents API

The PersonNameComponents automatic parser is very powerful. It can also detect name prefix and suffix. Look the example below:

let name = "Mr. John Lennon Da Silva, Ph.D."
var nameComponents = try PersonNameComponents(name)

print(nameComponents)

Resulting:

Screenshot 2021-12-09 at 08.06.10.png

Adding Nicknames

With PersonNameComponents API you can also add a nickname to it:

let name = "Mr. John Lennon Da Silva, Ph.D."
var nameComponents = try PersonNameComponents(name)
nameComponents.nickname = "Papy Jon"

print(nameComponents)

And the object will look like:

Screenshot 2021-12-09 at 08.10.35.png

Adding Phonetic Representation

The PersonNameComponents API also provides you a property where you can set the phonetic representation of a name. This property is also a PersonNameComponents.

This is important to increase accessibility of your apps. Imagine that you have a text to speech tool and it has to say the person's name. You can use phonetic representation to approximate the result for the user:

let name = "Mr. John Lennon Da Silva, Ph.D."
var nameComponents = try PersonNameComponents(name)
nameComponents.phoneticRepresentation = try PersonNameComponents("Mister Joonni Leenun The Silva")

print(nameComponents)

Adding Name Styles

The last but not least thing you can do is to apply automatic style to your names. With this tool you can generate name initials, or just the first name, you can crop prefix and suffix. Let's see that in practice:

let name = "Mr. John Lennon Da Silva, Ph.D."
var nameComponents = try PersonNameComponents(name)

print(nameComponents.formatted(.name(style: .abbreviated))," - abbreviated \n")
print(nameComponents.formatted(.name(style: .short))," - short \n")
print(nameComponents.formatted(.name(style: .medium))," - medium \n")
print(nameComponents.formatted(.name(style: .long))," - long \n")

Result in this:

Screenshot 2021-12-09 at 08.35.12.png

Summary

Apple gives to us a lot of great tools. Today we see how simple our life can be using one of them to automatically parse names. If you ever needed to parse person name, now you know you could have used the Foundation Framework to help you!

That's all my people, I hope you liked as I enjoyed write this article. If you want to support this blog you can Buy Me a Coffee or just leave a comment saying hello. You can also sponsor posts and I'm open to writing freelancing! Just reach me in LinkedIn or Twitter for details.

Thanks for the reading and... That's all folks.

credit: image

Did you find this article valuable?

Support Leonardo Maia Pugliese by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors
 
Share this