Swiftで、例えば数値から0埋めされた文字列にフォーマットする場合、`String`クラスのinit(format:_:)
コンストラクタを活用して次のように記述します。
print(String(format: "%02d", 0)) // "00"
なぜFoundation
フレームワークをインポートする必要があるのか?フォーマット文字列の仕様は?などの根拠がわからないままコピペして使うのは気持ち悪いですよね?
ということで納得できるまで調べ、フォーマット文字列の仕様とその情報へのたどり着き方、SwiftとObjective-Cとのつながりについてまとめました。
SwiftのStringクラスのinit(format:_:)の説明ではフォーマット文字列は不明
Swift
フレームワークのString
クラスのinit(format:_:)
の説明には、次の記述しかありません。
Returns a
String
object initialized by using a given format string as a template into which the remaining argument values are substituted.(テンプレートとしてのフォーマット文字列に続いて入力された値で置換して初期化されたStringオブジェクトを返す。)
この説明ではフォーマット文字列に何を指定すればいいのか、分かりませんね。
FoundationのNSStringクラスにフォーマット文字列の仕様へのリンクがある
Foundation
フレームワークのNSString
クラスのinit(format:arguments:)コンストラクタの説明から、String Format Specifiersへのリンクがあります。
String Format Specifiersのページからはさらに、"For more details, see the IEEE printf specification"という記述があります。
IEEE printf specificationの記述を確認すると、
- %が最初
- 続いてフラグ
- 0フラグを指定すると0埋めする
- フラグに続いて幅を指定(0フラグを指定していればその幅で0埋め)
のような記載があるので、フォーマット文字列の裏付けになります。
という記述にも、納得ができるようになりました。
SwiftのStringクラスはFoundationのNSStringクラスの機能を流用している
フォーマット文字列の仕様がどこにあるかは分かりました。
「Swift
フレームワークのString
クラスを使っているはずなのに、なぜFoundation
フレームワークのNSString
クラスのドキュメントを参照しなきゃいけないんだ?」
こんな疑問が浮かんでくると思います。
実はSwift
フレームワークのString
クラスは、部分的にFoundation
フレームワークのNSString
クラスの機能を流用しています。
そのためFoundation
フレームワークのインポートなしには、フォーマット機能が使えなかったりします。
print(String(format: "%02d", 0)) // "00"
また、SwiftUI
フレームワークを活用した開発の場合などは、import SwiftUI
とすると自動的にFoundation
フレームワークもインポートされるため、明示的にimport Foundation
とする必要はありません。
print(String(format: "%02d", 0)) // "00"
ちなみにSwiftUI
フレームワーク以外にも、Foundation
フレームワークの機能を内部で使っているライブラリをインポートすると、芋づる式にFoundation
フレームワークまでインポートされます。
なぜSwiftのStringクラスはFoundationのNSStringクラスの機能を流用しているのか?
Swiftプログラミング言語がリリースされたのは、2014年で、それ以前はObjective-Cを使ってアプリ開発されていました。Swiftで必要になる機能の多くが、Objective-Cのライブラリとして既に存在していたため、それらをFoundation
フレームワークとし、Swiftから流用できるよう設計されました。
Foundation
フレームワークのNSString
を明示的に使用しなくても、Swift
フレームワークのString
を使用すると裏ではNSString
の機能を使える親切設計にされましたが、この親切心が逆にあだとなり、Swift
フレームワークのString(format:_:)
コンストラクタの説明で、フォーマット文字列の仕様までしっかり記述されていないなど、Swift開発者にとってストレスフルな状況になってしまったのでした。
String(format:_:)
コンストラクタはFoundation
フレームワークをインポートしないと使えませんが、Foundation
フレームワークをインポートしなくても使える機能もあります。また、Foundation
フレームワークをインポートする前と後で挙動が変化する機能もあったりと、この辺りは若干カオスな仕様になっている点には注意が必要です。
"a".contains("") // Foundationをインポートすると結果はfalse