Swift

FormatStyle

Phililip
728x90

안녕하세요.

 

이번에는 iOS 15에 추가된 FormatStyle에 대해 간단하게 알아보고, Custom FormatStyle 만드는 방법도 같이 알아볼게요.

 


FormatStyle은 iOS 15에 추가된 프로토콜입니다.

 

기본으로 제공되는 style도 되게 여러 종류가 있어요.

(number, percent, timeDuration 등)

 

 

 

## 1. 기본 사용법

formatted() method를 사용하면 value -> string으로 변환되어서 출력되며, 자동으로 localization까지 지원해줍니다.

 

Date(timeIntervalSinceReferenceDate: 0).formatted()	// "1/1/2001, 9:00 AM"

Measurement(value: 20, unit: UnitDuration.minutes).formatted()	// "20 min"
Measurement(value: 300, unit: UnitLength.miles).formatted()	// "300 mi"

32.formatted()	// "32"

PersonNameComponents(givenName: "Philip", familyName: "Chung").formatted()	// Philip Chung
["Alba", "Bruce", "Carol", "Billson"].formatted()	// "Alba, Bruce, Carol, and Billson"

 

 

위에서 자동으로 localization까지 지원해준다고 했죠?

 

디바이스 언어를 한국어로 바꾸고 다시 실행시켜볼게요.

 

Date(timeIntervalSinceReferenceDate: 0).formatted()	// "2001. 1. 1. 오전 9:00"

Measurement(value: 20, unit: UnitDuration.minutes).formatted()	// "20 분"  
Measurement(value: 300, unit: UnitLength.miles).formatted()	// "300 mi"

32.formatted()	// "32"

PersonNameComponents(givenName: "Philip", familyName: "Chung").formatted()	// Philip Chung
["Alba", "Bruce", "Carol", "Billson"].formatted()	// "Alba, Bruce, Carol 및 Billson"

 

👍 👍 👍

 

 

 

## 2. Locale 설정

FormatStyle 프로토콜을 준수하는 구조체는 locale method를 사용해서 언어코드를 바꿔줄 수 있어요.

 

let thePast = Calendar(identifier: .gregorian).date(byAdding: .day, value: -14, to: Date())!
thePast.formatted(.relative(presentation: .numeric)) // "2 weeks ago"
let franceLocale = Locale(identifier: "ko_KR")
thePast.formatted(.relative(presentation: .numeric).locale(franceLocale)) // "2주 전"

 

 

 

 

## 3. Custom FormatStyle

FormatStyle 프로토콜을 채택해서 나만의 format(형식)을 만들어줄 수 있습니다.

 

우선 FormatStyle 프로토콜이 어떻게 생겼는지 볼게요.

 

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

    /// The type of data to format.
    associatedtype FormatInput

    /// The type of the formatted data.
    associatedtype FormatOutput

    /// Creates a `FormatOutput` instance from `value`.
    func format(_ value: Self.FormatInput) -> Self.FormatOutput

    /// If the format allows selecting a locale, returns a copy of this format with the new locale set. Default implementation returns an unmodified self.
    func locale(_ locale: Locale) -> Self
}

 

하나씩 살펴볼게요.

 

FormatInput은 처음 들어오는 데이터 타입을 의미합니다.

 

FormatOutput은 formatted(형태를 변환시킨) 데이터 타입을 의미합니다.

 

format method는 형태를 어떻게 바꿔줄지 직접적인 구현부가 들어가는 필수로 구현해야 하는 method입니다.

 

locale method는 locale 설정을 지원하고 싶을 경우 구현하며, 현재 인스턴스의 복사본을 리턴해줍니다.

 

 

 

그럼... 이제 직접 해봐야겠죠??ㅎㅎ

 

FormatStyle 프로토콜을 준수하는 구조체를 만들고, 숫자를 입력받아서 국내 화폐(₩) 형식으로 출력하는 FormatStyle을 구현해볼게요.

 

struct ToWon: FormatStyle {
    typealias FormatInput = Int
    typealias FormatOutput = String
}

 

숫자를 입력받을 것이니 FormatInput에는 Int 형이 들어갈 것이고,

 

형태를 변환했을 때는 문자열이니 FormatOutput에 String 형이 들어가야겠죠??

 

 

그다음엔 format method를 구현해줄게요.

 

struct ToWon: FormatStyle {
    typealias FormatInput = Int
    typealias FormatOutput = String
    
    func format(_ value: Int) -> String {    ✅
        value.formatted(.currency(code: "krw"))
    }
}

 

 

그 다음엔 FormatStyle을 extension 하여 toWon 스타일을 등록해줄게요.

 

extension FormatStyle where Self == ToWon {
    static var toWon: ToWon { .init() }
}

 

 

toWon 스타일을 직접 써보면

 

3000.formatted(ToWon()) // "₩3,000"

 

예쁘게 잘 나오는 것을 볼 수 있습니다ㅎㅎㅎ

 

 

 

## 참고

- https://ampersandsoftworks.com/posts/formatstyle-deep-dive/

 

FormatStyle Deep Dive

Apple introduced the new FormatStyle protocol with iOS 15. It allows for some truly remarkable things to happen when you’re converting your data into localized strings.

ampersandsoftworks.com

 

 

 


 

이번 글은 여기서 마무리.

 

 

 

반응형

'Swift' 카테고리의 다른 글

subscript  (0) 2022.04.03
Struct와 Class  (0) 2022.04.02
PersonNameComponents를 사용해서 이름 파싱하기  (0) 2022.03.23
[오픈소스] Flow  (0) 2022.03.16
precondition(_:_:file:line:)  (0) 2022.03.16