XCode9のGM Seedも出たということで、本格的に複数のプロジェクトでCodableを使い始めました。
だいぶ要領がつかめてきたところで、あー、最初から知ってれば良かったのに!と思ったハマりポイントを2つほどご紹介しておきます。
Type X does not conform to protocol Y 対策
class/structがコーディング(encode/decode)できない場合にこのエラーが出るわけですが、原因となった変数のところにエラーメッセージが出るならまだしも、class/struct宣言のところにだけエラーが出るので非常に分かりにくいです。そのような場合はひとまず以下の2点をチェックすると良いです。
-
Codableでない変数が入っているとエラー
当然といえば当然ですが、コーディングできない変数が含まれるclass/structはコーディングできません。特にカスタムのclass/struct、そしてenumはCodableプロトコルを実装している必要があります。中でもenumは、Codableプロトコルに適合させるためにrawValueを明示する必要があるなど一手間二手間かかります。 -
Keyを与える場合、初期値を与えないとエラー
初期値を var variable:Int = 0 のように明示的に初期値を与えてやらないと上述のエラーになるようです。これが分からなくてけっこうハマりました。Optionalの場合、デフォルトはnilだから省略してもいいだろうと思いがちですが、明示的に = nil を与えないと理解してもらえないみたいなので要注意です。
Decodeエラーをプリントするブロックは必ず記述しよう
そんなこと言われなくても、という人が大半かとも思いますが、エラーのcatch部分の記述方法を調べるのが面倒だったり、あとSwiftのtry?が便利だったりで、ついつい問題ある場合は「エラーです!」とだけprintすればいいや、みたいな感じでエラー処理を書くのをサボりがちになります。ですが、どんなに面倒でも最低限これだけは書いておいた方がいいです。
let data = ... /* Data to decode */
let decoder = JSONDecoder()
do {
let decoded = try decoder.decode(ResultObject.self, from: data)
} catch let error {
print("Error = \(error)")
}
Decoderがかなり厳密に型や値の有無をチェックするので、ちょっとのミスでもすぐデコードエラーになります。なので当然エラーをキャッチしてなぜ失敗したのが知る必要があるのですが、Swiftのcatch節の書き方に柔軟性がありすぎて、最低限どう書いていいのか分からなくてけっこう戸惑いました。結果的に上記のように catch let error
でエラーを拾ってprintすれば最低限の原因は把握できます。これがあるとないとだと効率がぜんぜん違うので、どんなに面倒でも catch let error { print("\(error)")}
だけは書くようにしましょう。