Swift4のCodableが内部で何をやっているか確認する

  • 26
    いいね
  • 0
    コメント

ほんの小ネタです。

Swift4から導入されるCodableですが、どういう仕組で実現されているんでしょうか。WWDCのプレゼンによるとCodableを適用すると、encode/decodeを実現するための実装をコンパイラーが生成してくれるようです。
https://developer.apple.com/videos/play/wwdc2017/212/?time=1755

実際にどんな実装が生成されるのか気になったので確認してみました。
以下のようなコードを準備します。

Sample.swift
struct Comic: Codable {
    let title: String
    let volume: Int
}

単純なstructCodableを適用しただけのコードです。これをSwift4のコンパイラに食わせて-print-astで字句構文解析&型チェック後の抽象構文木をPretty-Printさせてみます。

$ sudo xcode-select -s /path/to/Xcode9
$ swiftc -print-ast Sample.swift 

すると以下のような出力が得られます。

internal struct Comic : Codable {
  internal let title: String
  internal let volume: Int
  internal init(title: String, volume: Int)
  private enum CodingKeys : CodingKey {
    case title
    case volume
    internal var stringValue: String { get }
    internal init?(stringValue: String)
    internal var intValue: Int? { get }
    internal init?(intValue: Int)
    @_implements(Equatable, ==(_:_:)) internal static func __derived_enum_equals(_ a: Comic.CodingKeys, _ b: Comic.CodingKeys) -> Bool
    internal var hashValue: Int { get }
  }
  internal init(from decoder: Decoder) throws
  internal func encode(to encoder: Encoder) throws
}

プレゼンどおり、デコードに使うコンストラクタ、エンコードにつかうencodeメソッド、そしてJSONとオブジェクトのマッピングのためのCodingKyes型がコンパイラによって追加されていることがわかります。ASTが生成される段階で追加されるんですね。

既存のSwift用のJSONエンコード・デコードライブラリでは、どうしてもJSONとSwiftオブジェクトのマッピングを何らか記述する必要がありました。Swift4ではこのようにがっつりコンパイラーの支援を受けることで、Codableを適用するだけというシンプルな解決方法が可能になったということがわかります。