[Swift] FormatStyle の使い方

     
⌛️ 2 min.
WWDC21で導入された FormatStyle, ParseStrategy, ParseableFormatStyle を説明してみます。複数回に分けて説明します。まずは、FormatStyle の使い方から。
FormatStyle, ParseableFormatStyle の 使い方/作り方を理解するための記事シリーズです。
[Swift] FormatStyle の使い方 [Swift] ParseableFormatStyle の使い方 [Swift] FormatStyle の作り方 [Swift] ParseableFormatStyle の作り方

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Ventura 13.2.1
  • Xcode 14.3 Beta
  • iOS 16.0

フォーマット指定

Foundation には、日付(Date), 数値(Number) 等のさまざまなデータを表示するための文字列と相互変換するための仕組みが用意されています。

アプリを作成する時に必ずと言って良いくらい必要になる機能なので、非常に古くから存在しています。

一番初めは、C 言語の printf 相当のフォーマット指定子を使用した方法です。(逆変換は、scanf です)
次に、Objective-C では Formatter が導入され、その後 WWDC21 で、FormatStyle が発表されています。

順番におさらいしてみます。

数値をパーセント表示するケースを例に、それぞれで表示を行ってみています。

format 指定 の String

String を作成する時に、format 引数として渡すことで整形された String が作成されます。
先ほどのパーセントの例では、以下のようにすることで、40 を “40%” と変換することができます。

let myPercent = String(format: "%.0f%%", 40.0)
XCTAssertEqual(myPercent, "40%")

上記の %.0f が String Format Specifiers と呼ばれるものです。
Apple のドキュメントは、こちら

今でもよく使いますが、細かく制御できるように、指定できることも非常に多くなっていて、ドキュメントなしに書ける気がしません・・・

また、ローカライズも大変で、地域ごとに format 引数を変更することが必要となり、複雑化しやすいです。

良い点としては、直接出力フォーマットを指定している点です。
(なぜ、この表記になった?? というような疑問が湧きにくいです)

Formatter

Objective-C で導入されたのが Formatter です。
Format 対象のデータ型に合わせて、DateFormatter, NumberFormatter 等が用意されました。

Apple のドキュメントは、こちら

先ほどの パーセントの例では、NumberFormatter を使います。

let nf = NumberFormatter()
nf.numberStyle = .percent
let nfPercent = try XCTUnwrap(nf.string(from: 0.4))
XCTAssertEqual(nfPercent, "40%")

NumberFormatter が自分のスタイル指定を理解することができ、上記の場合は、.percent と指定されたことで、パーセント表示する ということを理解し必要な処理を行います。つまり、数値のあとに % の記号をつけるということです。

最初の例では、40 という数値を使用していましたが、NumberFormatter は、パーセントを扱うことを理解しているので、40% を意味する、0.4 を渡す必要があります。

さらに、NumberFormatter は、locale プロパティを持っていて locale に合わせた表記にしてくれます。
地域によって、表記が異なる場合には、NumberFormatter が ローカライズしてくれるということです。

アプリの都合等で、40% ではなく 40.0% というような小数点以下も含めた数値表記するというケースには 以下のように NumberFormatter を設定することで可能です。

let nf2 = NumberFormatter()
nf2.numberStyle = .percent
nf2.minimumFractionDigits = 1
let nf2Percent = try XCTUnwrap(nf2.string(from: 0.4))
XCTAssertEqual(nf2Percent, "40.0%")

上記は、スタイル指定することで、自動的に設定されるフォーマットを使っていますが、String のときのような直接フォーマットを指定する方法も用意されています。

Format に指定できるのは、Unicode で定めているものを使用します。ドキュメントは、こちら

let nf3 = NumberFormatter()
nf3.format = "00.0%"
let nf3Percent = try XCTUnwrap(nf3.string(from: 0.4))
XCTAssertEqual(nf3Percent, "40.0%")

numberStyle に percent を指定していないのに、40 ではなく 0.4 を渡している理由は、シンボルとして % を使用しているからです。(Unicode のドキュメントに説明されています)

Formatter は インスタンスを作るコストが高いので、できるだけ 1つのインスタンスを共有することが推奨されています。

FormatStyle

WWDC21 で説明されているのが FormatStyle です。

最初に使用例を説明します。

let percent = 40.formatted(.percent)
XCTAssertEqual(percent, "40%")

.formatted の引数に与えているのは、FormatStyle です。
具体的には、IntegerFormatStyle に static に定義されている Percent です。

FormatStyle

FormatStyle は、protocol です。

associatedType に FormatInput, FormatOutput が定義されており、format メソッドは、FormatInput を FormatOutput に変換します。

FormatStyle の Apple のドキュメントは、こちら

IntegerFormatStyle

具体例がないと、わかりにくいと思うので、IntegerFormatStyle を使って説明します。

# 実際には、Generics を使って定義されており若干複雑です。

IntegerFormatStyle のApple のドキュメントは、こちら

先ほども、例に挙げたように、データ.formatted(スタイル) と言う形で使用し、データを表現するための文字列に変換します。

// (Int)40 -> "40%"
let percent = 40.formatted(.percent)
XCTAssertEqual(percent, "40%")

データを適切な表現の文字列にしています。

やりたいことはシンプルですが、現実的には ケースバイケースで 使用したい表記が変わります。

表記のカスタマイズについて みてみます。
例えば、最初の例でも考えたような 小数点以下についても表記するフォーマットにしたい時です。
このような時には、.percent をカスタマイズして使います。

let percent2 = 40.formatted(.percent.precision(.fractionLength(1)))
XCTAssertEqual(percent2, "40.0%")

いわゆる chain スタイルで、カスタマイズできるようになっています。
上記は、precision(精度) に小数点一位 を指定した .percent スタイルを指定しています。

# ここでの精度は、数値自身の精度ではなく、表記する際に使用する精度ということです。

もう1つカスタマイズしてみます。
(何に使うか不明ですが、)数値部分を scientific 表記 いわゆる 1.0e4 のような 指数表記にしてみます。

let percent3 = 40.formatted(.percent.notation(.scientific))
XCTAssertEqual(percent3, "4E1%")

chain スタイルで続けることで、複数の指定が可能になります。

例えば、小数点第一位まで使った scientific 表記は、以下のような指定になります。

let percent4 = 40.formatted(.percent.notation(.scientific).precision(.fractionLength(1)))
XCTAssertEqual(percent4, "4.0E1%")

NumberFormatter/Formatter と比較してもシンプルに記述できることがわかります。

まとめ

FormatStyle を使った、データを表記する方法を確認しました。

FormatStyle の使い方
  • .formatted を使い、表記するための String に変換する
  • .formatted に与える FormatStyle で変換するフォーマットを指定する
  • IntegerFormatStyle をはじめ 複数の FormatStyle が用意されている
  • 表記のカスタマイズは、chain スタイルで指定する

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

SwiftUI おすすめ本

SwiftUI を理解するには、以下の本がおすすめです。

SwiftUI ViewMatery

SwiftUI で開発していくときに、ViewやLayoutのための適切なmodifierを探すのが大変です。
英語での説明になってしまいますが、以下の”SwiftUI Views Mastery Bundle”という本がビジュアル的に確認して探せるので、便利です。

英語ではありますが、1ページに コードと画面が並んでいるので、非常にわかりやすいです。

View に適用できる modifier もわかりやすく説明されているので、ビューの理解だけではなく、どのような装飾ができるかも簡単にわかります。

超便利です

SwiftUIViewsMastery

販売元のページは、こちらです。

SwiftUI 徹底入門

# SwiftUI は、毎年大きく改善されていますので、少し古くなってしまいましたが、いまでも 定番本です。

Swift学習におすすめの本

詳解Swift

Swift の学習には、詳解 Swift という書籍が、おすすめです。

著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。

最新版を購入するのがおすすめです。

現時点では、上記の Swift 5 に対応した第5版が最新版です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です