6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UserDefaultsに辞書型を入れるとき、KeyはStringでなければならないという制約がある

Posted at

UserDefaultsに辞書型を突っ込んだ際に、こんなエラーになりました。

Attempt to set a non-property-list object

このときは突っ込んだのが辞書型で、KeyにInt型、Valueに配列が入ったちょっと複雑なやつだったので、
配列がHashableじゃなかったからダメなのかな〜と思って(←誤解)、
突っ込もうとしていたデータを分割して、
Keyだけの配列、Valueだけの配列をそれぞれUserDefaultsに突っ込んで、配列のindexで紐付けようかと思ったんですが、
これでもできなくはないんですが、バグがあったときに収集つかなくなるなと思い、ちゃんと原因を調べました。

辞書型のKeyにできる値

まず僕が最初にした誤解について。

@frozen struct Dictionary where Key : Hashable

辞書型のKeyはHashableである必要があります。
ただValueに関しては自由なので、配列でも辞書型でも突っ込めます。
Hashableに準拠しているかどうかは、公式ドキュメントかXcodeで定義を参照するかするとわかりますが、
IntやStringなど標準的な型はHashableです。
ただ、ArrayやDictionaryはHashableには準拠していないので、Keyにはできません。

※公式ドキュメント見ると、Conforms Toの中にHashableがあるので、一瞬準拠しているように見えるのですが、「Conforms when Value conforms to Hashable.」と注意書きがあります。

property-listとは?

どうやらエラーの原因は辞書型のエラーというよりは、UserDefaultsのエラーっぽいぞ? と気づきました。
僕が打ち込もうとしていた型は、KeyをInt型にしていたので、Hashableはクリアしています。
というかそもそもエラー文はそんなこと言っていない。。。
エラーに真面目に向き合ってみると、Property Listsに入っていないことが問題っぽいですが……?

About Property Lists

この一覧を見る限り、Dictionaryも使えるはずで、NSDictionaryにキャストするといけるのかな? とか試してみたんですが、結果は変わらず。

ところが、

And although NSDictionary and CFDictionary objects allow their keys to be objects of any type, if the keys are not string objects, the collections are not property-list objects

ん?

if the keys are not string objects, the collections are not property-list objects

えーっ!

というわけで、KeyをInt型→String型にキャストしたら解決しました。
StringにキャストできないKeyを使いたい方は、一度Data型(JSON Decodeを使うといいみたい)にすると突っ込めるらしいです。

参考

[Int:String]はUserDefaultsに入れると実行時エラー

6
3
0

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
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?