안녕하세요.
이번에는 이름을 등록하면 알아서 파싱이 되는 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
이번 글은 여기서 마무리.
'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 |