👻

個人的UserDefaultを使うときの注意点

2023/01/28に公開

この記事の目的

iOSアプリ開発ではアプリの設定等、長期間小さな値を保存しておくのにUserDefaultという領域を非常に重宝する。
 しかし、UserDefaultの値を使う際、いくつか注意が必要だと考えたので、備忘録として記事にする。

参考資料

当記事は、以下のApple Developerの公式ドキュメントからいくつかの箇所をかいつまみ、記事とする。
https://developer.apple.com/documentation/foundation/userdefaults

そもそもUserDefaultとは?

いわば、「iOSがアプリ毎に用意してくれる簡易的なデータベース」 である。

詳しい説明は他の人が丁寧に解説した記事があるのでそれを参照してほしい。

とりあえず、この記事では以下の三つの特徴を理解していれば良い。

  1. iOS上にアプリが存在する限り永久に使える
  2. UserDefaultは各アプリに用意され、それぞれのアプリに紐付いて保存される
  3. 紐付いているアプリを削除すると、UserDefaultは消去される。

UserDefaultの使い方

わかりやすくまとめてくださっている記事があったのでこちらを参照してほしい。
https://qiita.com/uhooi/items/429cac9b798b9c0937ae

上の記事をかいつまむと、

UserDefaultへの保存

保存する際は、以下のコードを組み込むだけである。

UserDefaults.standard.set({}, forKey: {String})

UserDefaultの削除

削除する際は、以下のコードを組み込むだけである。

UserDefaults.standard.set({}, forKey: {String})

UserDefaultから読み出す方法

上で紹介した記事の通り、読み出すときは以下のように、

UserDefaults.standard.object(forKey: {キー})
UserDefaults.standard.string(forKey: {キー})
UserDefaults.standard.array(forKey: {キー})
UserDefaults.standard.dictionary(forKey: {キー})
UserDefaults.standard.data(forKey: {キー})
UserDefaults.standard.stringArray(forKey: {キー})
UserDefaults.standard.integer(forKey: {キー})
UserDefaults.standard.float(forKey: {キー})
UserDefaults.standard.double(forKey: {キー})
UserDefaults.standard.bool(forKey: {キー})
UserDefaults.standard.url(forKey: {キー})

取り出したいデータをキーと共にを指定しなければならない。
ここにデフォルトで用意されていない型での取り出し方は上の記事を参照してほしい。

読み出すときの注意点

オプショナル型で返ってくる型は以下の通り。
非数値型のとき、オプショナル型で返ってくる。

UserDefaults.standard.object(forKey: {キー}) -> Any?
UserDefaults.standard.string(forKey: {キー}) -> String?
UserDefaults.standard.array(forKey: {キー}) -> [Any]? 
UserDefaults.standard.dictionary(forKey: {キー}) -> [String: Any]?
UserDefaults.standard.data(forKey: {キー}) -> Data?
UserDefaults.standard.stringArray(forKey: {キー}) -> [String]?
UserDefaults.standard.url(forKey: {キー}) -> URL?

それに対して、以下の数値型で読み出すときは非オプショナル型で返ってくる。

UserDefaults.standard.integer(forKey: {キー}) -> Int
UserDefaults.standard.float(forKey: {キー}) ->  Float
UserDefaults.standard.double(forKey: {キー}) -> Double
UserDefaults.standard.bool(forKey: {キー}) -> Bool

Q. なぜ、オプショナル型で返ってくる型があるのか?

A. キーに紐付いた値が入っていない場合があるから。

これは至極当然といえば当然なのだが、UserDefaultを読み出すタイミングによっては指定されたキーに値が入っていない場合があるのだ。

そうした場合に、非数値型の型を指定した場合はnilで値を返す必要があり、それを受け止めてるためにオプショナル型である必要があるのだ。

Q. では、オプショナル型で読み出されない数値型では何が返ってくるのか?

A. 「0」

<参考:公式Document>
https://developer.apple.com/documentation/foundation/userdefaults/1407405-integer

なぜか、数値型では0で返ってくる。

しかも不思議なことに、キーにsetした値が読み出そうとした型でなくとも取り出すことが可能である。

つまり、setしたときの型がString型であったとしても、読み出すときInt型を指定したときは、Int型で返ってくるのだ。
例:

let stringNum: String = "123"
UserDefaults.standard.set(stringNum, forKey: "Key")

let intNum = UserDefaults.standard.integer(forKey: "Key")
print(intNum) //123

まとめ

UserDefaultから読み出すときは

  • 非数値型 -> オプショナル型
  • 数値型 -> 非オプショナル型

この違いに気をつけよう!

Discussion