いったいどうなってるんだってばよ!!
print(String(1234))
// -> 1234
print("\(1234)")
// -> 1234
もちろん、普通に変数展開されたStringをprintしても3桁区切りにはなりません。
どうやら、変数展開している箇所にこの不思議な挙動の秘密がありそうです。
この挙動は一体なんなのか
調べてみたところ、こちらの記事に出会いました。すごくよくまとまっていて、Int以外の変数展開についても書かれているのでぜひこちらも見てみてください。(Textの変数展開にImageや別のText入れられるの知らなかった...)
要約すると
- SwiftUI.Textはイニシャライザの引数として
LocalizedStringKey
を受け取る -
LocalizedStringKey
はExpressibleByStringInterpolation
に準拠する型で、StringInterpolationProtocol
に準拠した型StringInterpolation
を内部的に持っている - SwiftUI は
LocalizedStringKey.StringInterpolation
を拡張したappendInterpolation
を定義することで、カスタマイズされた変数展開が利用できるようになっている
このような実装によって、カスタマイズされた変数展開ができるようになっています。
その上で今回の挙動について紹介
SwiftUIに定義されている appendInterpolation
には public mutating func appendInterpolation<T>(_ value: T) where T : _FormatSpecifiable
というメソッドがあり、今回の挙動はこれが関係しています。
public protocol _FormatSpecifiable : Swift.Equatable {
associatedtype _Arg : Swift.CVarArg
var _arg: Self._Arg { get }
var _specifier: Swift.String { get }
}
_FormatSpecifiable
の定義は上のようになっていて
extension Int : SwiftUI._FormatSpecifiable
extension Int8 : SwiftUI._FormatSpecifiable
extension Int16 : SwiftUI._FormatSpecifiable
extension Int32 : SwiftUI._FormatSpecifiable
extension Int64 : SwiftUI._FormatSpecifiable
extension UInt : SwiftUI._FormatSpecifiable
extension UInt8 : SwiftUI._FormatSpecifiable
extension UInt16 : SwiftUI._FormatSpecifiable
extension UInt32 : SwiftUI._FormatSpecifiable
extension UInt64 : SwiftUI._FormatSpecifiable
extension Float : SwiftUI._FormatSpecifiable
extension Double : SwiftUI._FormatSpecifiable
extension CGFloat : SwiftUI._FormatSpecifiable
Int
や Double
などの数値型が _FormatSpecifiable
に準拠していることがわかります。
ちなみに、Doubleを渡すと
%.6f
相当のフォーマットがされていて、フォーマットのされ方も数値型によって違っているようです。
この _FormatSpecifiable
を拡張した実装の中身までは確認できなかったのですが、 appendInterpolation
には他にも public mutating func appendInterpolation<T>(_ value: T, specifier: String) where T : _FormatSpecifiable
メソッドが生えてきて、
のような使い方ができるため、各種の数値型に対して上のような文字列フォーマット指定子が _specifier
でそれぞれ設定されているのだと思われます。