Swift

PersonNameComponents를 사용해서 이름 파싱하기

Phililip
728x90

안녕하세요.

 

이번에는 이름을 등록하면 알아서 파싱이 되는 PersonNameComponents에 대해 알아볼게요.

 


보통 이름을 파싱 하고 싶다면, 문자열을 split(separator:) method를 사용해서 파싱 하는 방법을 가장 쉽게 떠올릴 수 있습니다.

 

하지만, 우리의 갓플은 PersonNameComponents라는 구조체를 제공해주고 있었어요...ㅎ

 

요게 편리한 기능들을 이것저것 가지고 있더라구요??ㅎㅎㅎ...

 

그래서 한번 알아보려고 합니다.

 

 

 

## 1. PersonNameComponents 사용법

PersonNameComponents는 아래처럼 사용할 수 있어요.

 

let name = "John Lennon"
var nameComponents = try PersonNameComponents(name)
print(nameComponents)       // givenName: John familyName: Lennon

 

이때 유의할 점은, PersonNameComponents가 error를 throw 한다는 점이에요.

 

 

만약 성과 이름을 미리 알고 있을 땐, 아래처럼 일일이 설정해줄 수도 있어요.

 

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

 

이때는 error를 throw하지 않습니다ㅎㅎ

 

 

만약 이름에 복잡한 규칙이 있을 경우, 직접 파싱 규칙을 정의할 수 있어요.


ParseStrategy라는 규칙을 직접 만들고 PersonNameComponents에 전달하는 방식이며, 이 방법은 iOS 15부터 사용할 수 있어요.

 

 

 

## 2. ParseStrategy (iOS 15 이상)

ParseStrategy는 아래처럼 정의되어 있어요.

 

/// 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     // 파싱 규칙을 정의하는 함수
}

 

 

만약 암호화된 string을 ParseStrategy에 정의된 파싱 규칙으로 이름을 뽑아낸다고 가정한다면,

 

아래처럼 구현이 가능해요.

 

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
        }
    }
}

let name = "1"
var nameComponents = try PersonNameComponents(name, strategy: NameParser())
print(nameComponents)       // givenName: Lola middleName: Pa familyName: Loza

 

문자열 1 -> ParseStrategy 파싱 규칙을 통해서 -> PersonNameComponents("Lola Pa Loza")가 만들어진 것이죠ㅎㅎ

 

 

 

## 3. PersonNameComponents 기타 기능

name prefix, name suffix까지 알아서 파싱 해줍니다.

 

let name = "Mr. John Lennon Da Silva, Ph.D."
var nameComponents = try PersonNameComponents(name)
print(nameComponents)	// namePrefix: Mr. givenName: John middleName: Lennon familyName: Da Silva nameSuffix: Ph.D.

 

 

닉네임도 추가할 수 있어요!

 

e = "Mr. John Lennon Da Silva, Ph.D."
var nameComponents = try PersonNameComponents(name)
nameComponents.nickname = "Papy Jon"
print(nameComponents)	// namePrefix: Mr. givenName: John middleName: Lennon familyName: Da Silva nameSuffix: Ph.D. nickname: Papy Jon

 

 

 

## 4. Phonetic Representation

Phonetic Representation을 사용하면 TTS(Text to Speech)로 읽어줄 텍스트를 지정해줄 수 있어요.

 

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

 

 

 

## 5. Name Style 지정

PersonNameComponents에서 full name으로 사용할지, 성만 가져와서 사용할 지 등 포맷을 지정해줄 수 있습니다.

 

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

print(nameComponents.formatted(.name(style: .abbreviated))," - abbreviated")    // JD  - abbreviated 
print(nameComponents.formatted(.name(style: .short))," - short")                // John  - short 
print(nameComponents.formatted(.name(style: .medium))," - medium")              // John Da Silva  - medium 
print(nameComponents.formatted(.name(style: .long))," - long")                  // Mr. John Lennon Da Silva Ph.D.  - long

 

 

 

## 6. 한글 이름 파싱

애플이니.. 영어 이름은 당연히 파싱 해주겠지... 근데 한글 이름은????

 

이라는 생각이 들어서 한번 테스트해봤어요ㅋㅋㅋ

 

 

일반적인 이름(성 1글자, 이름 2글자)을 넣어보면?

 

let name = "정필립"
var nameComponents = try PersonNameComponents(name)
print(nameComponents)       // givenName: 필립 familyName: 정

 

오오......

 

 

 

외자라면??

 

let name = "윤현"
var nameComponents = try PersonNameComponents(name)
print(nameComponents)       // givenName: 현 familyName: 윤

 

오오오.....

 

 

 

이름이 4글자라면???

 

let name = "정아무개"
var nameComponents = try PersonNameComponents(name)
print(nameComponents)       // givenName: 아무개 familyName: 정

 

오오오오........

 

 

 

만약 성이 2글자, 이름이 1글자라면? (ex. 남궁x)

 

let name = "남궁민"
var nameComponents = try PersonNameComponents(name)
print(nameComponents)       // givenName: 민 familyName: 남궁

 

오오오오오!!

 

 

 

성이 2글자, 이름도 2글자라면?

 

let name = "남궁민수"
var nameComponents = try PersonNameComponents(name)
print(nameComponents)       // givenName: 민수 familyName: 남궁

 

오오오오오오옼ㅋㅋㅋㅋ

 

 

 

그 외 몇 가지 테스트를 해보고 한글 이름 파싱 규칙을 유추해보자면,

 

애플은 한국에서 일반적으로 사용되는 성씨(김, 이, 박, 정, 윤, 남궁 등) 리스트를 가지고 있고, 한글 이름 앞에 성씨가 있는지 검사하는 것 같아요.

 

만약 정필립이 아닌 적필립으로 했을 때 familyName을 못 읽더라고요??ㅎㅎ

 

let name = "적필립"
var nameComponents = try PersonNameComponents(name)
print(nameComponents)       // givenName: 적필립

 

그냥 재미로만 참고해주세요ㅎㅎ

 

 

 

 

## 참고

- https://holyswift.app/using-swift-to-parse-person-name-with-ios-15-apis

 

Using Swift to Parse Person Name with iOS 15 APIs

What is your name?

holyswift.app

 

 


 

이번 글은 여기서 마무리.

 

 

 

반응형

'Swift' 카테고리의 다른 글

Struct와 Class  (0) 2022.04.02
FormatStyle  (0) 2022.03.24
[오픈소스] Flow  (0) 2022.03.16
precondition(_:_:file:line:)  (0) 2022.03.16
[Swift 5.6] Swift 5.6 추가된 기능들  (1) 2022.03.12