いったいどうなってるんだってばよ!!
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 でそれぞれ設定されているのだと思われます。



