Sequenceのformatted()を試す

開発環境

> xcodebuild -version
Xcode 14.0
Build version 14A5229c

Xcodeはbetaだが本記事の内容はiOS16未満のAPIを使用。

モチベーション

Sequenceを読んでいたら知らないメソッドがあったので使ってみる。

ドキュメント

SequenceのElementがStringのときに使用可能。 よくあることだが情報量がほぼ無い。困った。

使ってみる

import Foundation

let array = [
    "Apple",
    "Banana",
    "Cherry",
    "Grape"
]
array.formatted()
// -> Apple, Banana, Cherry, and Grape

!? 何も指定しない場合は英語チックな(A, B, and Cみたいな)表現になる模様。ただ連結されるかと予想していたが、通常の連結はjoinedがあるしなあという感じで、まだ使い勝手が理解できていない。

WWDCのセッションを見る

developer.apple.com

formattedはiOS15からの追加のため去年のWWDCにセッションがあるのでは?と思い、探したらあった。14:30からformatの話。

let numbers = [1, 2, 3]
numbers.formatted(
    .list(
        memberStyle: .percent,
        type: .and
    )
)
// -> 1%, 2%, and 3%

数値のリストをformatするコードが紹介されていた。一方でStringのリスト自体にformatの柔軟性は少なそう。前述したA, B, and Cみたいな(あとor)連結ができるだけっぽい。

なぜStringオンリー?

冒頭で記載したformatted()は、記載通りSequenceのElementがStringのときのみ使える。一方でElementがString以外の時はformatted(_:)を使って引数にFormatStyleを渡す必要がある。

let array = [
    "りんご",
    "バナナ",
    "さくらんぼ",
    "グレープ"
]

// ✅
array.formatted()


let numbers = [1, 2, 3]

// ❌
numbers.formatted() 

// ✅
numbers.formatted(
    .list(
        memberStyle: .percent,
        type: .and
    )
)

引数無しのformat()は以下と同じ結果が得られる

let array = [
    "Apple",
    "Banana",
    "Cherry",
    "Grape"
]
let a = array.formatted()
let b = array.formatted(.list(type: .and))

print(a == b)
// -> true 
// ("Apple, Banana, Cherry, and Grape")

背景は分からないが、デフォルトとして formatted(.list(type: .and)) と同じ結果が得られるようになっている。一番使われる形と想定して引数無しでこの結果になるようにしたのかな。分からん。実際に使う時は分かりやすさの観点で明示的に引数を渡したい。

所感

使ったこと無いAPIを試すことから始まって、WWDCのセッションを見たり手元で複数のAPIを試したりと学びになった。WWDCのセッションが分かりやすかったのでもっと見ていきたい機運。

参考