質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

655閲覧

Codableを使ってUserDefaultsからデータを読み込みたい

退会済みユーザー

退会済みユーザー

総合スコア0

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2020/06/15 09:32

前提・実現したいこと

UserDefaultsを使用して値をやり取りするアプリを作成しています。
カスタムクラスをUserDefaultsで取り扱うために、Codableを使って値をUserDefaultsに読み書きしようと試みています。

発生している問題・エラーメッセージ

UserDefaultsに保存した値をdecodeすると、値がnilになってしまう

該当のソースコード(簡単の為にPlaygroundで動確しています)

Swift5

1//: A UIKit based Playground for presenting user interface 2 3import UIKit 4import PlaygroundSupport 5 6class List:Codable { 7 8 var text: String? 9 10 init(text: String) { 11 12 self.text = text 13 14 } 15} 16 17class MyViewController : UIViewController { 18 19 20 21 var listItems: [List] = [] 22 23 24 override func loadView() { 25 let view = UIView() 26 view.backgroundColor = .white 27 28 let label = UILabel() 29 label.frame = CGRect(x: 150, y: 200, width: 200, height: 20) 30 label.text = "Hello World!" 31 label.textColor = .black 32 33 view.addSubview(label) 34 self.view = view 35 36 //UserDefaultsにデータを保存 37 listItems.append(List(text: "test")) 38 let archivedData = try? JSONEncoder().encode(listItems) 39 UserDefaults.standard.set(archivedData, forKey: "List") 40 41 //UserDefaultsからデータを読み込み 42 let data = UserDefaults.standard.data(forKey: "List") 43 let unarchivedObject = try? JSONDecoder().decode(List.self, from: data!) 44 } 45} 46PlaygroundPage.current.liveView = MyViewController() 47

試したこと

let data = UserDefaults.standard.data(forKey: "List")
には値があるのですが、

let unarchivedObject = try? JSONDecoder().decode(List.self, from: data!)
でnilになっているようです。

恐らくキャストの仕方がイマイチなのかと思いますが、デバッグしきれずにおります。
お力添えいただけないでしょうか。

補足情報(FW/ツールのバージョンなど)

Swift5
Xcode11.5

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MasakiHori

2020/06/15 09:48

try? をつかわずに do {} catch {} で例外を出力してみてください
退会済みユーザー

退会済みユーザー

2020/06/15 12:19

ありがとうございます。 do{   try JSONDecoder().decode(List.self, from: data!); } catch {  print("ERROR: \(error)") } で ERROR: typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil)) という出力が得られました。 Listを配列として入力していないことが原因かなと思い try JSONDecoder().decode([List].self, from: data!) としたら狙いのデコードになりました。 ありがとうございました。 もう一個だけお願いなんですが、 きちんと現象を理解したいので、今回の問題点を解説していただけないでしょうか?(すいません)
guest

回答1

0

ベストアンサー

すみません。
エラーしか読んでませんでした。
自己解決したようですね。

swift

1var listItems: [List] = [] 2... 3 4let archivedData = try? JSONEncoder().encode(listItems)

としていますので、生成されたJSONは[List]をエンコードしたものになっていますので、[List]としてデコードするよう指示しなければなりません。

エラーの内容ですが、JSONにはList型はありませんので辞書(SwiftではDictionary<String, Any>に相当する)として記録されてます。なのでちょっとヘンテコなエラーになってしまっています。


swift

1let unarchivedObject = try? JSONDecoder().decode(List.self, from: data!)

この部分が

swift

1let unarchivedObject = try? JSONDecoder().decode([List].self, from: data!) 2 3//あるいは 4let unarchivedObject = try? JSONDecoder().decode(Array<List>.self, from: data!)

こうですね。

投稿2020/06/16 01:07

編集2020/06/16 01:18
MasakiHori

総合スコア3391

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/06/16 05:07

ありがとうございます。大変勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問