LoginSignup
3
1

More than 3 years have passed since last update.

SwiftのDictionary生成時のデータの並び順はランタイムで変わる

Last updated at Posted at 2018-10-21

概要

SwiftのDictionaryは順番が保証されないですが、それでトラブったので調べたことを書きます。

事の発端

Xcodeをアップデートした後にiOS側で生成したJSON文字列の並びが毎回違うことが発覚。
その後調査したところアプリの起動毎にDictionary型のデータの並び順が変わっていたのでJSONのデータの並び順が変わっていた事がわかりました。

何が起こってたのか?

Dictionary生成時に記載した順番と生成されたデータの順番が変わってました。
スクリーンショット 2018-10-21 14.58.07.png

以前は順番が変わらなかったのですが、
ランタイムで生成されたDictionaryの順番が変わるみたいです。

いつ頃から起こってたか?

おそらくXcode9.4あたり...?

コマンドラインツールなど環境が根本原因なのか古いXcodeを入れ直しても再現できませんでした。

恥ずかしながらXcodeのアップデートを怠っていたのでXcode10で発覚。
Xcode9.3だと問題が発覚しなかったのと、古い別のMacに残ってたXcode9.4.1で検証しても起きてたのでこのあたりが怪しそうです。

ただDictionaryで順番担保しないのは知ってたので、これはコードを書いた側のミスですね...
環境再現ができなかったのでわからずじまいですが、型推論で別の型になってたりなんてのもありえるのかもしれません。

Dictionaryおさらい

Dictionaryは変更を加える際には順番は保証できるけどそれ以外はできないとのこと。
たぶんremoveとかのmutationでは順番は変更されないとかですかね。

The order of key-value pairs in a dictionary is stable between mutations but is otherwise unpredictable.

Dictionary - Swift Standard Library | Apple Developer Documentation

解決策

JSONの生成時に順番が保証されてればいい場合

JSONSerialization.WritingOptionssortedKeysを使いましょう。
key順番でソートしてくれます。

sortedKeys - JSONSerialization.WritingOptions | Apple Developer Documentation

ただiOS11からなのでiOS10は爆発するしかない。

Dictionaryで順番も担保したい場合

順番を担保したいなら実行速度が遅いけどDictionaryLiteralってのがあるよだそうです。

 If you need an ordered collection of key-value pairs and don’t need the fast key lookup that Dictionary provides, see the DictionaryLiteral type for an alternative.

DictionaryLiteral - Swift Standard Library | Apple Developer Documentation

使ってみたところkey-valueのtupleをArrayにしたみたいな感じで使い勝手が悪いので役に立たなそう。
当然ながらJSONにできないです。

スクリーンショット 2018-10-21 15.22.19.png

使い所が思い浮かばないのでうまい使い方があるのか知りたいです。

まとめ

  • ドキュメントはちゃんと読んでから開発しましょう
  • JSONの文字列生成時にはオプションでsortedKeysをつけると順番を固定できます
3
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1